• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * mISDNinfineon.c
3  *		Support for cards based on following Infineon ISDN chipsets
4  *		- ISAC + HSCX
5  *		- IPAC and IPAC-X
6  *		- ISAC-SX + HSCX
7  *
8  * Supported cards:
9  *		- Dialogic Diva 2.0
10  *		- Dialogic Diva 2.0U
11  *		- Dialogic Diva 2.01
12  *		- Dialogic Diva 2.02
13  *		- Sedlbauer Speedwin
14  *		- HST Saphir3
15  *		- Develo (former ELSA) Microlink PCI (Quickstep 1000)
16  *		- Develo (former ELSA) Quickstep 3000
17  *		- Berkom Scitel BRIX Quadro
18  *		- Dr.Neuhaus (Sagem) Niccy
19  *
20  *
21  *
22  * Author       Karsten Keil <keil@isdn4linux.de>
23  *
24  * Copyright 2009  by Karsten Keil <keil@isdn4linux.de>
25  *
26  * This program is free software; you can redistribute it and/or modify
27  * it under the terms of the GNU General Public License version 2 as
28  * published by the Free Software Foundation.
29  *
30  * This program is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33  * GNU General Public License for more details.
34  *
35  * You should have received a copy of the GNU General Public License
36  * along with this program; if not, write to the Free Software
37  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38  *
39  */
40 
41 #include <linux/interrupt.h>
42 #include <linux/module.h>
43 #include <linux/pci.h>
44 #include <linux/delay.h>
45 #include <linux/mISDNhw.h>
46 #include <linux/slab.h>
47 #include "ipac.h"
48 
49 #define INFINEON_REV	"1.0"
50 
51 static int inf_cnt;
52 static u32 debug;
53 static u32 irqloops = 4;
54 
55 enum inf_types {
56 	INF_NONE,
57 	INF_DIVA20,
58 	INF_DIVA20U,
59 	INF_DIVA201,
60 	INF_DIVA202,
61 	INF_SPEEDWIN,
62 	INF_SAPHIR3,
63 	INF_QS1000,
64 	INF_QS3000,
65 	INF_NICCY,
66 	INF_SCT_1,
67 	INF_SCT_2,
68 	INF_SCT_3,
69 	INF_SCT_4,
70 	INF_GAZEL_R685,
71 	INF_GAZEL_R753
72 };
73 
74 enum addr_mode {
75 	AM_NONE = 0,
76 	AM_IO,
77 	AM_MEMIO,
78 	AM_IND_IO,
79 };
80 
81 struct inf_cinfo {
82 	enum inf_types	typ;
83 	const char	*full;
84 	const char	*name;
85 	enum addr_mode	cfg_mode;
86 	enum addr_mode	addr_mode;
87 	u8		cfg_bar;
88 	u8		addr_bar;
89 	void		*irqfunc;
90 };
91 
92 struct _ioaddr {
93 	enum addr_mode	mode;
94 	union {
95 		void __iomem	*p;
96 		struct _ioport	io;
97 	} a;
98 };
99 
100 struct _iohandle {
101 	enum addr_mode	mode;
102 	resource_size_t	size;
103 	resource_size_t	start;
104 	void __iomem	*p;
105 };
106 
107 struct inf_hw {
108 	struct list_head	list;
109 	struct pci_dev		*pdev;
110 	const struct inf_cinfo	*ci;
111 	char			name[MISDN_MAX_IDLEN];
112 	u32			irq;
113 	u32			irqcnt;
114 	struct _iohandle	cfg;
115 	struct _iohandle	addr;
116 	struct _ioaddr		isac;
117 	struct _ioaddr		hscx;
118 	spinlock_t		lock;	/* HW access lock */
119 	struct ipac_hw		ipac;
120 	struct inf_hw		*sc[3];	/* slave cards */
121 };
122 
123 
124 #define PCI_SUBVENDOR_HST_SAPHIR3       0x52
125 #define PCI_SUBVENDOR_SEDLBAUER_PCI     0x53
126 #define PCI_SUB_ID_SEDLBAUER            0x01
127 
128 static struct pci_device_id infineon_ids[] = {
129 	{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 },
130 	{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U },
131 	{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 },
132 	{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA202), INF_DIVA202 },
133 	{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
134 	  PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
135 	  INF_SPEEDWIN },
136 	{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
137 	  PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3 },
138 	{ PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_MICROLINK), INF_QS1000 },
139 	{ PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_QS3000), INF_QS3000 },
140 	{ PCI_VDEVICE(SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY), INF_NICCY },
141 	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
142 	  PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
143 	  INF_SCT_1 },
144 	{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R685), INF_GAZEL_R685 },
145 	{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R753), INF_GAZEL_R753 },
146 	{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO), INF_GAZEL_R753 },
147 	{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_OLITEC), INF_GAZEL_R753 },
148 	{ }
149 };
150 MODULE_DEVICE_TABLE(pci, infineon_ids);
151 
152 /* PCI interface specific defines */
153 /* Diva 2.0/2.0U */
154 #define DIVA_HSCX_PORT		0x00
155 #define DIVA_HSCX_ALE		0x04
156 #define DIVA_ISAC_PORT		0x08
157 #define DIVA_ISAC_ALE		0x0C
158 #define DIVA_PCI_CTRL           0x10
159 
160 /* DIVA_PCI_CTRL bits */
161 #define DIVA_IRQ_BIT		0x01
162 #define DIVA_RESET_BIT		0x08
163 #define DIVA_EEPROM_CLK		0x40
164 #define DIVA_LED_A		0x10
165 #define DIVA_LED_B		0x20
166 #define DIVA_IRQ_CLR		0x80
167 
168 /* Diva 2.01/2.02 */
169 /* Siemens PITA */
170 #define PITA_ICR_REG		0x00
171 #define PITA_INT0_STATUS	0x02
172 
173 #define PITA_MISC_REG		0x1c
174 #define PITA_PARA_SOFTRESET	0x01000000
175 #define PITA_SER_SOFTRESET	0x02000000
176 #define PITA_PARA_MPX_MODE	0x04000000
177 #define PITA_INT0_ENABLE	0x00020000
178 
179 /* TIGER 100 Registers */
180 #define TIGER_RESET_ADDR	0x00
181 #define TIGER_EXTERN_RESET	0x01
182 #define TIGER_AUX_CTRL		0x02
183 #define TIGER_AUX_DATA		0x03
184 #define TIGER_AUX_IRQMASK	0x05
185 #define TIGER_AUX_STATUS	0x07
186 
187 /* Tiger AUX BITs */
188 #define TIGER_IOMASK		0xdd	/* 1 and 5 are inputs */
189 #define TIGER_IRQ_BIT		0x02
190 
191 #define TIGER_IPAC_ALE		0xC0
192 #define TIGER_IPAC_PORT		0xC8
193 
194 /* ELSA (now Develo) PCI cards */
195 #define ELSA_IRQ_ADDR		0x4c
196 #define ELSA_IRQ_MASK		0x04
197 #define QS1000_IRQ_OFF		0x01
198 #define QS3000_IRQ_OFF		0x03
199 #define QS1000_IRQ_ON		0x41
200 #define QS3000_IRQ_ON		0x43
201 
202 /* Dr Neuhaus/Sagem Niccy */
203 #define NICCY_ISAC_PORT		0x00
204 #define NICCY_HSCX_PORT		0x01
205 #define NICCY_ISAC_ALE		0x02
206 #define NICCY_HSCX_ALE		0x03
207 
208 #define NICCY_IRQ_CTRL_REG	0x38
209 #define NICCY_IRQ_ENABLE	0x001f00
210 #define NICCY_IRQ_DISABLE	0xff0000
211 #define NICCY_IRQ_BIT		0x800000
212 
213 
214 /* Scitel PLX */
215 #define SCT_PLX_IRQ_ADDR	0x4c
216 #define SCT_PLX_RESET_ADDR	0x50
217 #define SCT_PLX_IRQ_ENABLE	0x41
218 #define SCT_PLX_RESET_BIT	0x04
219 
220 /* Gazel */
221 #define	GAZEL_IPAC_DATA_PORT	0x04
222 /* Gazel PLX */
223 #define GAZEL_CNTRL		0x50
224 #define GAZEL_RESET		0x04
225 #define GAZEL_RESET_9050	0x40000000
226 #define GAZEL_INCSR		0x4C
227 #define GAZEL_ISAC_EN		0x08
228 #define GAZEL_INT_ISAC		0x20
229 #define GAZEL_HSCX_EN		0x01
230 #define GAZEL_INT_HSCX		0x04
231 #define GAZEL_PCI_EN		0x40
232 #define GAZEL_IPAC_EN		0x03
233 
234 
235 static LIST_HEAD(Cards);
236 static DEFINE_RWLOCK(card_lock); /* protect Cards */
237 
238 static void
_set_debug(struct inf_hw * card)239 _set_debug(struct inf_hw *card)
240 {
241 	card->ipac.isac.dch.debug = debug;
242 	card->ipac.hscx[0].bch.debug = debug;
243 	card->ipac.hscx[1].bch.debug = debug;
244 }
245 
246 static int
set_debug(const char * val,struct kernel_param * kp)247 set_debug(const char *val, struct kernel_param *kp)
248 {
249 	int ret;
250 	struct inf_hw *card;
251 
252 	ret = param_set_uint(val, kp);
253 	if (!ret) {
254 		read_lock(&card_lock);
255 		list_for_each_entry(card, &Cards, list)
256 			_set_debug(card);
257 		read_unlock(&card_lock);
258 	}
259 	return ret;
260 }
261 
262 MODULE_AUTHOR("Karsten Keil");
263 MODULE_LICENSE("GPL v2");
264 MODULE_VERSION(INFINEON_REV);
265 module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
266 MODULE_PARM_DESC(debug, "infineon debug mask");
267 module_param(irqloops, uint, S_IRUGO | S_IWUSR);
268 MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
269 
270 /* Interface functions */
271 
272 IOFUNC_IO(ISAC, inf_hw, isac.a.io)
273 IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
274 IOFUNC_IND(ISAC, inf_hw, isac.a.io)
275 IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
276 IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
277 IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
278 
279 static irqreturn_t
diva_irq(int intno,void * dev_id)280 diva_irq(int intno, void *dev_id)
281 {
282 	struct inf_hw *hw = dev_id;
283 	u8 val;
284 
285 	spin_lock(&hw->lock);
286 	val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
287 	if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
288 		spin_unlock(&hw->lock);
289 		return IRQ_NONE; /* shared */
290 	}
291 	hw->irqcnt++;
292 	mISDNipac_irq(&hw->ipac, irqloops);
293 	spin_unlock(&hw->lock);
294 	return IRQ_HANDLED;
295 }
296 
297 static irqreturn_t
diva20x_irq(int intno,void * dev_id)298 diva20x_irq(int intno, void *dev_id)
299 {
300 	struct inf_hw *hw = dev_id;
301 	u8 val;
302 
303 	spin_lock(&hw->lock);
304 	val = readb(hw->cfg.p);
305 	if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
306 		spin_unlock(&hw->lock);
307 		return IRQ_NONE; /* shared */
308 	}
309 	hw->irqcnt++;
310 	mISDNipac_irq(&hw->ipac, irqloops);
311 	writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
312 	spin_unlock(&hw->lock);
313 	return IRQ_HANDLED;
314 }
315 
316 static irqreturn_t
tiger_irq(int intno,void * dev_id)317 tiger_irq(int intno, void *dev_id)
318 {
319 	struct inf_hw *hw = dev_id;
320 	u8 val;
321 
322 	spin_lock(&hw->lock);
323 	val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
324 	if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
325 		spin_unlock(&hw->lock);
326 		return IRQ_NONE; /* shared */
327 	}
328 	hw->irqcnt++;
329 	mISDNipac_irq(&hw->ipac, irqloops);
330 	spin_unlock(&hw->lock);
331 	return IRQ_HANDLED;
332 }
333 
334 static irqreturn_t
elsa_irq(int intno,void * dev_id)335 elsa_irq(int intno, void *dev_id)
336 {
337 	struct inf_hw *hw = dev_id;
338 	u8 val;
339 
340 	spin_lock(&hw->lock);
341 	val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
342 	if (!(val & ELSA_IRQ_MASK)) {
343 		spin_unlock(&hw->lock);
344 		return IRQ_NONE; /* shared */
345 	}
346 	hw->irqcnt++;
347 	mISDNipac_irq(&hw->ipac, irqloops);
348 	spin_unlock(&hw->lock);
349 	return IRQ_HANDLED;
350 }
351 
352 static irqreturn_t
niccy_irq(int intno,void * dev_id)353 niccy_irq(int intno, void *dev_id)
354 {
355 	struct inf_hw *hw = dev_id;
356 	u32 val;
357 
358 	spin_lock(&hw->lock);
359 	val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
360 	if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
361 		spin_unlock(&hw->lock);
362 		return IRQ_NONE; /* shared */
363 	}
364 	outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
365 	hw->irqcnt++;
366 	mISDNipac_irq(&hw->ipac, irqloops);
367 	spin_unlock(&hw->lock);
368 	return IRQ_HANDLED;
369 }
370 
371 static irqreturn_t
gazel_irq(int intno,void * dev_id)372 gazel_irq(int intno, void *dev_id)
373 {
374 	struct inf_hw *hw = dev_id;
375 	irqreturn_t ret;
376 
377 	spin_lock(&hw->lock);
378 	ret = mISDNipac_irq(&hw->ipac, irqloops);
379 	spin_unlock(&hw->lock);
380 	return ret;
381 }
382 
383 static irqreturn_t
ipac_irq(int intno,void * dev_id)384 ipac_irq(int intno, void *dev_id)
385 {
386 	struct inf_hw *hw = dev_id;
387 	u8 val;
388 
389 	spin_lock(&hw->lock);
390 	val = hw->ipac.read_reg(hw, IPAC_ISTA);
391 	if (!(val & 0x3f)) {
392 		spin_unlock(&hw->lock);
393 		return IRQ_NONE; /* shared */
394 	}
395 	hw->irqcnt++;
396 	mISDNipac_irq(&hw->ipac, irqloops);
397 	spin_unlock(&hw->lock);
398 	return IRQ_HANDLED;
399 }
400 
401 static void
enable_hwirq(struct inf_hw * hw)402 enable_hwirq(struct inf_hw *hw)
403 {
404 	u16 w;
405 	u32 val;
406 
407 	switch (hw->ci->typ) {
408 	case INF_DIVA201:
409 	case INF_DIVA202:
410 		writel(PITA_INT0_ENABLE, hw->cfg.p);
411 		break;
412 	case INF_SPEEDWIN:
413 	case INF_SAPHIR3:
414 		outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
415 		break;
416 	case INF_QS1000:
417 		outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
418 		break;
419 	case INF_QS3000:
420 		outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
421 		break;
422 	case INF_NICCY:
423 		val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
424 		val |= NICCY_IRQ_ENABLE;
425 		outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
426 		break;
427 	case INF_SCT_1:
428 		w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
429 		w |= SCT_PLX_IRQ_ENABLE;
430 		outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
431 		break;
432 	case INF_GAZEL_R685:
433 		outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
434 		     (u32)hw->cfg.start + GAZEL_INCSR);
435 		break;
436 	case INF_GAZEL_R753:
437 		outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
438 		     (u32)hw->cfg.start + GAZEL_INCSR);
439 		break;
440 	default:
441 		break;
442 	}
443 }
444 
445 static void
disable_hwirq(struct inf_hw * hw)446 disable_hwirq(struct inf_hw *hw)
447 {
448 	u16 w;
449 	u32 val;
450 
451 	switch (hw->ci->typ) {
452 	case INF_DIVA201:
453 	case INF_DIVA202:
454 		writel(0, hw->cfg.p);
455 		break;
456 	case INF_SPEEDWIN:
457 	case INF_SAPHIR3:
458 		outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
459 		break;
460 	case INF_QS1000:
461 		outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
462 		break;
463 	case INF_QS3000:
464 		outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
465 		break;
466 	case INF_NICCY:
467 		val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
468 		val &= NICCY_IRQ_DISABLE;
469 		outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
470 		break;
471 	case INF_SCT_1:
472 		w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
473 		w &= (~SCT_PLX_IRQ_ENABLE);
474 		outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
475 		break;
476 	case INF_GAZEL_R685:
477 	case INF_GAZEL_R753:
478 		outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
479 		break;
480 	default:
481 		break;
482 	}
483 }
484 
485 static void
ipac_chip_reset(struct inf_hw * hw)486 ipac_chip_reset(struct inf_hw *hw)
487 {
488 	hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
489 	mdelay(5);
490 	hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
491 	mdelay(5);
492 	hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
493 	hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
494 }
495 
496 static void
reset_inf(struct inf_hw * hw)497 reset_inf(struct inf_hw *hw)
498 {
499 	u16 w;
500 	u32 val;
501 
502 	if (debug & DEBUG_HW)
503 		pr_notice("%s: resetting card\n", hw->name);
504 	switch (hw->ci->typ) {
505 	case INF_DIVA20:
506 	case INF_DIVA20U:
507 		outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
508 		mdelay(10);
509 		outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
510 		mdelay(10);
511 		/* Workaround PCI9060 */
512 		outb(9, (u32)hw->cfg.start + 0x69);
513 		outb(DIVA_RESET_BIT | DIVA_LED_A,
514 		     (u32)hw->cfg.start + DIVA_PCI_CTRL);
515 		break;
516 	case INF_DIVA201:
517 		writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
518 		       hw->cfg.p + PITA_MISC_REG);
519 		mdelay(1);
520 		writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
521 		mdelay(10);
522 		break;
523 	case INF_DIVA202:
524 		writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
525 		       hw->cfg.p + PITA_MISC_REG);
526 		mdelay(1);
527 		writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
528 		       hw->cfg.p + PITA_MISC_REG);
529 		mdelay(10);
530 		break;
531 	case INF_SPEEDWIN:
532 	case INF_SAPHIR3:
533 		ipac_chip_reset(hw);
534 		hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
535 		hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
536 		hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
537 		break;
538 	case INF_QS1000:
539 	case INF_QS3000:
540 		ipac_chip_reset(hw);
541 		hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
542 		hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
543 		hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
544 		break;
545 	case INF_NICCY:
546 		break;
547 	case INF_SCT_1:
548 		w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
549 		w &= (~SCT_PLX_RESET_BIT);
550 		outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
551 		mdelay(10);
552 		w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
553 		w |= SCT_PLX_RESET_BIT;
554 		outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
555 		mdelay(10);
556 		break;
557 	case INF_GAZEL_R685:
558 		val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
559 		val |= (GAZEL_RESET_9050 + GAZEL_RESET);
560 		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
561 		val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
562 		mdelay(4);
563 		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
564 		mdelay(10);
565 		hw->ipac.isac.adf2 = 0x87;
566 		hw->ipac.hscx[0].slot = 0x1f;
567 		hw->ipac.hscx[1].slot = 0x23;
568 		break;
569 	case INF_GAZEL_R753:
570 		val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
571 		val |= (GAZEL_RESET_9050 + GAZEL_RESET);
572 		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
573 		val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
574 		mdelay(4);
575 		outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
576 		mdelay(10);
577 		ipac_chip_reset(hw);
578 		hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
579 		hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
580 		hw->ipac.conf = 0x01; /* IOM off */
581 		break;
582 	default:
583 		return;
584 	}
585 	enable_hwirq(hw);
586 }
587 
588 static int
inf_ctrl(struct inf_hw * hw,u32 cmd,u_long arg)589 inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
590 {
591 	int ret = 0;
592 
593 	switch (cmd) {
594 	case HW_RESET_REQ:
595 		reset_inf(hw);
596 		break;
597 	default:
598 		pr_info("%s: %s unknown command %x %lx\n",
599 			hw->name, __func__, cmd, arg);
600 		ret = -EINVAL;
601 		break;
602 	}
603 	return ret;
604 }
605 
606 static int
init_irq(struct inf_hw * hw)607 init_irq(struct inf_hw *hw)
608 {
609 	int	ret, cnt = 3;
610 	u_long	flags;
611 
612 	if (!hw->ci->irqfunc)
613 		return -EINVAL;
614 	ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
615 	if (ret) {
616 		pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
617 		return ret;
618 	}
619 	while (cnt--) {
620 		spin_lock_irqsave(&hw->lock, flags);
621 		reset_inf(hw);
622 		ret = hw->ipac.init(&hw->ipac);
623 		if (ret) {
624 			spin_unlock_irqrestore(&hw->lock, flags);
625 			pr_info("%s: ISAC init failed with %d\n",
626 				hw->name, ret);
627 			break;
628 		}
629 		spin_unlock_irqrestore(&hw->lock, flags);
630 		msleep_interruptible(10);
631 		if (debug & DEBUG_HW)
632 			pr_notice("%s: IRQ %d count %d\n", hw->name,
633 				  hw->irq, hw->irqcnt);
634 		if (!hw->irqcnt) {
635 			pr_info("%s: IRQ(%d) got no requests during init %d\n",
636 				hw->name, hw->irq, 3 - cnt);
637 		} else
638 			return 0;
639 	}
640 	free_irq(hw->irq, hw);
641 	return -EIO;
642 }
643 
644 static void
release_io(struct inf_hw * hw)645 release_io(struct inf_hw *hw)
646 {
647 	if (hw->cfg.mode) {
648 		if (hw->cfg.mode == AM_MEMIO) {
649 			release_mem_region(hw->cfg.start, hw->cfg.size);
650 			if (hw->cfg.p)
651 				iounmap(hw->cfg.p);
652 		} else
653 			release_region(hw->cfg.start, hw->cfg.size);
654 		hw->cfg.mode = AM_NONE;
655 	}
656 	if (hw->addr.mode) {
657 		if (hw->addr.mode == AM_MEMIO) {
658 			release_mem_region(hw->addr.start, hw->addr.size);
659 			if (hw->addr.p)
660 				iounmap(hw->addr.p);
661 		} else
662 			release_region(hw->addr.start, hw->addr.size);
663 		hw->addr.mode = AM_NONE;
664 	}
665 }
666 
667 static int
setup_io(struct inf_hw * hw)668 setup_io(struct inf_hw *hw)
669 {
670 	int err = 0;
671 
672 	if (hw->ci->cfg_mode) {
673 		hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
674 		hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
675 		if (hw->ci->cfg_mode == AM_MEMIO) {
676 			if (!request_mem_region(hw->cfg.start, hw->cfg.size,
677 						hw->name))
678 				err = -EBUSY;
679 		} else {
680 			if (!request_region(hw->cfg.start, hw->cfg.size,
681 					    hw->name))
682 				err = -EBUSY;
683 		}
684 		if (err) {
685 			pr_info("mISDN: %s config port %lx (%lu bytes)"
686 				"already in use\n", hw->name,
687 				(ulong)hw->cfg.start, (ulong)hw->cfg.size);
688 			return err;
689 		}
690 		hw->cfg.mode = hw->ci->cfg_mode;
691 		if (hw->ci->cfg_mode == AM_MEMIO) {
692 			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
693 			if (!hw->cfg.p)
694 				return -ENOMEM;
695 		}
696 		if (debug & DEBUG_HW)
697 			pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
698 				  hw->name, (ulong)hw->cfg.start,
699 				  (ulong)hw->cfg.size, hw->ci->cfg_mode);
700 
701 	}
702 	if (hw->ci->addr_mode) {
703 		hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
704 		hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
705 		if (hw->ci->addr_mode == AM_MEMIO) {
706 			if (!request_mem_region(hw->addr.start, hw->addr.size,
707 						hw->name))
708 				err = -EBUSY;
709 		} else {
710 			if (!request_region(hw->addr.start, hw->addr.size,
711 					    hw->name))
712 				err = -EBUSY;
713 		}
714 		if (err) {
715 			pr_info("mISDN: %s address port %lx (%lu bytes)"
716 				"already in use\n", hw->name,
717 				(ulong)hw->addr.start, (ulong)hw->addr.size);
718 			return err;
719 		}
720 		hw->addr.mode = hw->ci->addr_mode;
721 		if (hw->ci->addr_mode == AM_MEMIO) {
722 			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
723 			if (!hw->addr.p)
724 				return -ENOMEM;
725 		}
726 		if (debug & DEBUG_HW)
727 			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
728 				  hw->name, (ulong)hw->addr.start,
729 				  (ulong)hw->addr.size, hw->ci->addr_mode);
730 
731 	}
732 
733 	switch (hw->ci->typ) {
734 	case INF_DIVA20:
735 	case INF_DIVA20U:
736 		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
737 		hw->isac.mode = hw->cfg.mode;
738 		hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
739 		hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
740 		hw->hscx.mode = hw->cfg.mode;
741 		hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
742 		hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
743 		break;
744 	case INF_DIVA201:
745 		hw->ipac.type = IPAC_TYPE_IPAC;
746 		hw->ipac.isac.off = 0x80;
747 		hw->isac.mode = hw->addr.mode;
748 		hw->isac.a.p = hw->addr.p;
749 		hw->hscx.mode = hw->addr.mode;
750 		hw->hscx.a.p = hw->addr.p;
751 		break;
752 	case INF_DIVA202:
753 		hw->ipac.type = IPAC_TYPE_IPACX;
754 		hw->isac.mode = hw->addr.mode;
755 		hw->isac.a.p = hw->addr.p;
756 		hw->hscx.mode = hw->addr.mode;
757 		hw->hscx.a.p = hw->addr.p;
758 		break;
759 	case INF_SPEEDWIN:
760 	case INF_SAPHIR3:
761 		hw->ipac.type = IPAC_TYPE_IPAC;
762 		hw->ipac.isac.off = 0x80;
763 		hw->isac.mode = hw->cfg.mode;
764 		hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
765 		hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
766 		hw->hscx.mode = hw->cfg.mode;
767 		hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
768 		hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
769 		outb(0xff, (ulong)hw->cfg.start);
770 		mdelay(1);
771 		outb(0x00, (ulong)hw->cfg.start);
772 		mdelay(1);
773 		outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
774 		break;
775 	case INF_QS1000:
776 	case INF_QS3000:
777 		hw->ipac.type = IPAC_TYPE_IPAC;
778 		hw->ipac.isac.off = 0x80;
779 		hw->isac.a.io.ale = (u32)hw->addr.start;
780 		hw->isac.a.io.port = (u32)hw->addr.start + 1;
781 		hw->isac.mode = hw->addr.mode;
782 		hw->hscx.a.io.ale = (u32)hw->addr.start;
783 		hw->hscx.a.io.port = (u32)hw->addr.start + 1;
784 		hw->hscx.mode = hw->addr.mode;
785 		break;
786 	case INF_NICCY:
787 		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
788 		hw->isac.mode = hw->addr.mode;
789 		hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
790 		hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
791 		hw->hscx.mode = hw->addr.mode;
792 		hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
793 		hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
794 		break;
795 	case INF_SCT_1:
796 		hw->ipac.type = IPAC_TYPE_IPAC;
797 		hw->ipac.isac.off = 0x80;
798 		hw->isac.a.io.ale = (u32)hw->addr.start;
799 		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
800 		hw->isac.mode = hw->addr.mode;
801 		hw->hscx.a.io.ale = hw->isac.a.io.ale;
802 		hw->hscx.a.io.port = hw->isac.a.io.port;
803 		hw->hscx.mode = hw->addr.mode;
804 		break;
805 	case INF_SCT_2:
806 		hw->ipac.type = IPAC_TYPE_IPAC;
807 		hw->ipac.isac.off = 0x80;
808 		hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
809 		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
810 		hw->isac.mode = hw->addr.mode;
811 		hw->hscx.a.io.ale = hw->isac.a.io.ale;
812 		hw->hscx.a.io.port = hw->isac.a.io.port;
813 		hw->hscx.mode = hw->addr.mode;
814 		break;
815 	case INF_SCT_3:
816 		hw->ipac.type = IPAC_TYPE_IPAC;
817 		hw->ipac.isac.off = 0x80;
818 		hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
819 		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
820 		hw->isac.mode = hw->addr.mode;
821 		hw->hscx.a.io.ale = hw->isac.a.io.ale;
822 		hw->hscx.a.io.port = hw->isac.a.io.port;
823 		hw->hscx.mode = hw->addr.mode;
824 		break;
825 	case INF_SCT_4:
826 		hw->ipac.type = IPAC_TYPE_IPAC;
827 		hw->ipac.isac.off = 0x80;
828 		hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
829 		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
830 		hw->isac.mode = hw->addr.mode;
831 		hw->hscx.a.io.ale = hw->isac.a.io.ale;
832 		hw->hscx.a.io.port = hw->isac.a.io.port;
833 		hw->hscx.mode = hw->addr.mode;
834 		break;
835 	case INF_GAZEL_R685:
836 		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
837 		hw->ipac.isac.off = 0x80;
838 		hw->isac.mode = hw->addr.mode;
839 		hw->isac.a.io.port = (u32)hw->addr.start;
840 		hw->hscx.mode = hw->addr.mode;
841 		hw->hscx.a.io.port = hw->isac.a.io.port;
842 		break;
843 	case INF_GAZEL_R753:
844 		hw->ipac.type = IPAC_TYPE_IPAC;
845 		hw->ipac.isac.off = 0x80;
846 		hw->isac.mode = hw->addr.mode;
847 		hw->isac.a.io.ale = (u32)hw->addr.start;
848 		hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
849 		hw->hscx.mode = hw->addr.mode;
850 		hw->hscx.a.io.ale = hw->isac.a.io.ale;
851 		hw->hscx.a.io.port = hw->isac.a.io.port;
852 		break;
853 	default:
854 		return -EINVAL;
855 	}
856 	switch (hw->isac.mode) {
857 	case AM_MEMIO:
858 		ASSIGN_FUNC_IPAC(MIO, hw->ipac);
859 		break;
860 	case AM_IND_IO:
861 		ASSIGN_FUNC_IPAC(IND, hw->ipac);
862 		break;
863 	case AM_IO:
864 		ASSIGN_FUNC_IPAC(IO, hw->ipac);
865 		break;
866 	default:
867 		return -EINVAL;
868 	}
869 	return 0;
870 }
871 
872 static void
release_card(struct inf_hw * card)873 release_card(struct inf_hw *card) {
874 	ulong	flags;
875 	int	i;
876 
877 	spin_lock_irqsave(&card->lock, flags);
878 	disable_hwirq(card);
879 	spin_unlock_irqrestore(&card->lock, flags);
880 	card->ipac.isac.release(&card->ipac.isac);
881 	free_irq(card->irq, card);
882 	mISDN_unregister_device(&card->ipac.isac.dch.dev);
883 	release_io(card);
884 	write_lock_irqsave(&card_lock, flags);
885 	list_del(&card->list);
886 	write_unlock_irqrestore(&card_lock, flags);
887 	switch (card->ci->typ) {
888 	case INF_SCT_2:
889 	case INF_SCT_3:
890 	case INF_SCT_4:
891 		break;
892 	case INF_SCT_1:
893 		for (i = 0; i < 3; i++) {
894 			if (card->sc[i])
895 				release_card(card->sc[i]);
896 			card->sc[i] = NULL;
897 		}
898 	default:
899 		pci_disable_device(card->pdev);
900 		pci_set_drvdata(card->pdev, NULL);
901 		break;
902 	}
903 	kfree(card);
904 	inf_cnt--;
905 }
906 
907 static int
setup_instance(struct inf_hw * card)908 setup_instance(struct inf_hw *card)
909 {
910 	int err;
911 	ulong flags;
912 
913 	snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
914 		 inf_cnt + 1);
915 	write_lock_irqsave(&card_lock, flags);
916 	list_add_tail(&card->list, &Cards);
917 	write_unlock_irqrestore(&card_lock, flags);
918 
919 	_set_debug(card);
920 	card->ipac.isac.name = card->name;
921 	card->ipac.name = card->name;
922 	card->ipac.owner = THIS_MODULE;
923 	spin_lock_init(&card->lock);
924 	card->ipac.isac.hwlock = &card->lock;
925 	card->ipac.hwlock = &card->lock;
926 	card->ipac.ctrl = (void *)&inf_ctrl;
927 
928 	err = setup_io(card);
929 	if (err)
930 		goto error_setup;
931 
932 	card->ipac.isac.dch.dev.Bprotocols =
933 		mISDNipac_init(&card->ipac, card);
934 
935 	if (card->ipac.isac.dch.dev.Bprotocols == 0)
936 		goto error_setup;
937 
938 	err = mISDN_register_device(&card->ipac.isac.dch.dev,
939 				    &card->pdev->dev, card->name);
940 	if (err)
941 		goto error;
942 
943 	err = init_irq(card);
944 	if (!err)  {
945 		inf_cnt++;
946 		pr_notice("Infineon %d cards installed\n", inf_cnt);
947 		return 0;
948 	}
949 	mISDN_unregister_device(&card->ipac.isac.dch.dev);
950 error:
951 	card->ipac.release(&card->ipac);
952 error_setup:
953 	release_io(card);
954 	write_lock_irqsave(&card_lock, flags);
955 	list_del(&card->list);
956 	write_unlock_irqrestore(&card_lock, flags);
957 	return err;
958 }
959 
960 static const struct inf_cinfo inf_card_info[] = {
961 	{
962 		INF_DIVA20,
963 		"Dialogic Diva 2.0",
964 		"diva20",
965 		AM_IND_IO, AM_NONE, 2, 0,
966 		&diva_irq
967 	},
968 	{
969 		INF_DIVA20U,
970 		"Dialogic Diva 2.0U",
971 		"diva20U",
972 		AM_IND_IO, AM_NONE, 2, 0,
973 		&diva_irq
974 	},
975 	{
976 		INF_DIVA201,
977 		"Dialogic Diva 2.01",
978 		"diva201",
979 		AM_MEMIO, AM_MEMIO, 0, 1,
980 		&diva20x_irq
981 	},
982 	{
983 		INF_DIVA202,
984 		"Dialogic Diva 2.02",
985 		"diva202",
986 		AM_MEMIO, AM_MEMIO, 0, 1,
987 		&diva20x_irq
988 	},
989 	{
990 		INF_SPEEDWIN,
991 		"Sedlbauer SpeedWin PCI",
992 		"speedwin",
993 		AM_IND_IO, AM_NONE, 0, 0,
994 		&tiger_irq
995 	},
996 	{
997 		INF_SAPHIR3,
998 		"HST Saphir 3",
999 		"saphir",
1000 		AM_IND_IO, AM_NONE, 0, 0,
1001 		&tiger_irq
1002 	},
1003 	{
1004 		INF_QS1000,
1005 		"Develo Microlink PCI",
1006 		"qs1000",
1007 		AM_IO, AM_IND_IO, 1, 3,
1008 		&elsa_irq
1009 	},
1010 	{
1011 		INF_QS3000,
1012 		"Develo QuickStep 3000",
1013 		"qs3000",
1014 		AM_IO, AM_IND_IO, 1, 3,
1015 		&elsa_irq
1016 	},
1017 	{
1018 		INF_NICCY,
1019 		"Sagem NICCY",
1020 		"niccy",
1021 		AM_IO, AM_IND_IO, 0, 1,
1022 		&niccy_irq
1023 	},
1024 	{
1025 		INF_SCT_1,
1026 		"SciTel Quadro",
1027 		"p1_scitel",
1028 		AM_IO, AM_IND_IO, 1, 5,
1029 		&ipac_irq
1030 	},
1031 	{
1032 		INF_SCT_2,
1033 		"SciTel Quadro",
1034 		"p2_scitel",
1035 		AM_NONE, AM_IND_IO, 0, 4,
1036 		&ipac_irq
1037 	},
1038 	{
1039 		INF_SCT_3,
1040 		"SciTel Quadro",
1041 		"p3_scitel",
1042 		AM_NONE, AM_IND_IO, 0, 3,
1043 		&ipac_irq
1044 	},
1045 	{
1046 		INF_SCT_4,
1047 		"SciTel Quadro",
1048 		"p4_scitel",
1049 		AM_NONE, AM_IND_IO, 0, 2,
1050 		&ipac_irq
1051 	},
1052 	{
1053 		INF_GAZEL_R685,
1054 		"Gazel R685",
1055 		"gazel685",
1056 		AM_IO, AM_IO, 1, 2,
1057 		&gazel_irq
1058 	},
1059 	{
1060 		INF_GAZEL_R753,
1061 		"Gazel R753",
1062 		"gazel753",
1063 		AM_IO, AM_IND_IO, 1, 2,
1064 		&ipac_irq
1065 	},
1066 	{
1067 		INF_NONE,
1068 	}
1069 };
1070 
1071 static const struct inf_cinfo *
get_card_info(enum inf_types typ)1072 get_card_info(enum inf_types typ)
1073 {
1074 	const struct inf_cinfo *ci = inf_card_info;
1075 
1076 	while (ci->typ != INF_NONE) {
1077 		if (ci->typ == typ)
1078 			return ci;
1079 		ci++;
1080 	}
1081 	return NULL;
1082 }
1083 
1084 static int
inf_probe(struct pci_dev * pdev,const struct pci_device_id * ent)1085 inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1086 {
1087 	int err = -ENOMEM;
1088 	struct inf_hw *card;
1089 
1090 	card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1091 	if (!card) {
1092 		pr_info("No memory for Infineon ISDN card\n");
1093 		return err;
1094 	}
1095 	card->pdev = pdev;
1096 	err = pci_enable_device(pdev);
1097 	if (err) {
1098 		kfree(card);
1099 		return err;
1100 	}
1101 	card->ci = get_card_info(ent->driver_data);
1102 	if (!card->ci) {
1103 		pr_info("mISDN: do not have information about adapter at %s\n",
1104 			pci_name(pdev));
1105 		kfree(card);
1106 		pci_disable_device(pdev);
1107 		return -EINVAL;
1108 	} else
1109 		pr_notice("mISDN: found adapter %s at %s\n",
1110 			  card->ci->full, pci_name(pdev));
1111 
1112 	card->irq = pdev->irq;
1113 	pci_set_drvdata(pdev, card);
1114 	err = setup_instance(card);
1115 	if (err) {
1116 		pci_disable_device(pdev);
1117 		kfree(card);
1118 		pci_set_drvdata(pdev, NULL);
1119 	} else if (ent->driver_data == INF_SCT_1) {
1120 		int i;
1121 		struct inf_hw *sc;
1122 
1123 		for (i = 1; i < 4; i++) {
1124 			sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1125 			if (!sc) {
1126 				release_card(card);
1127 				pci_disable_device(pdev);
1128 				return -ENOMEM;
1129 			}
1130 			sc->irq = card->irq;
1131 			sc->pdev = card->pdev;
1132 			sc->ci = card->ci + i;
1133 			err = setup_instance(sc);
1134 			if (err) {
1135 				pci_disable_device(pdev);
1136 				kfree(sc);
1137 				release_card(card);
1138 				break;
1139 			} else
1140 				card->sc[i - 1] = sc;
1141 		}
1142 	}
1143 	return err;
1144 }
1145 
1146 static void
inf_remove(struct pci_dev * pdev)1147 inf_remove(struct pci_dev *pdev)
1148 {
1149 	struct inf_hw	*card = pci_get_drvdata(pdev);
1150 
1151 	if (card)
1152 		release_card(card);
1153 	else
1154 		pr_debug("%s: drvdata already removed\n", __func__);
1155 }
1156 
1157 static struct pci_driver infineon_driver = {
1158 	.name = "ISDN Infineon pci",
1159 	.probe = inf_probe,
1160 	.remove = inf_remove,
1161 	.id_table = infineon_ids,
1162 };
1163 
1164 static int __init
infineon_init(void)1165 infineon_init(void)
1166 {
1167 	int err;
1168 
1169 	pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1170 	err = pci_register_driver(&infineon_driver);
1171 	return err;
1172 }
1173 
1174 static void __exit
infineon_cleanup(void)1175 infineon_cleanup(void)
1176 {
1177 	pci_unregister_driver(&infineon_driver);
1178 }
1179 
1180 module_init(infineon_init);
1181 module_exit(infineon_cleanup);
1182