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
51static int inf_cnt;
52static u32 debug;
53static u32 irqloops = 4;
54
55enum 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
74enum addr_mode {
75	AM_NONE = 0,
76	AM_IO,
77	AM_MEMIO,
78	AM_IND_IO,
79};
80
81struct 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
92struct _ioaddr {
93	enum addr_mode	mode;
94	union {
95		void __iomem	*p;
96		struct _ioport	io;
97	} a;
98};
99
100struct _iohandle {
101	enum addr_mode	mode;
102	resource_size_t	size;
103	resource_size_t	start;
104	void __iomem	*p;
105};
106
107struct 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
128static 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};
150MODULE_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
235static LIST_HEAD(Cards);
236static DEFINE_RWLOCK(card_lock); /* protect Cards */
237
238static void
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
246static int
247set_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
262MODULE_AUTHOR("Karsten Keil");
263MODULE_LICENSE("GPL v2");
264MODULE_VERSION(INFINEON_REV);
265module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
266MODULE_PARM_DESC(debug, "infineon debug mask");
267module_param(irqloops, uint, S_IRUGO | S_IWUSR);
268MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
269
270/* Interface functions */
271
272IOFUNC_IO(ISAC, inf_hw, isac.a.io)
273IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
274IOFUNC_IND(ISAC, inf_hw, isac.a.io)
275IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
276IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
277IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
278
279static irqreturn_t
280diva_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
297static irqreturn_t
298diva20x_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
316static irqreturn_t
317tiger_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
334static irqreturn_t
335elsa_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
352static irqreturn_t
353niccy_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
371static irqreturn_t
372gazel_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
383static irqreturn_t
384ipac_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
401static void
402enable_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
445static void
446disable_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
485static void
486ipac_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
496static void
497reset_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
588static int
589inf_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
606static int
607init_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
644static void
645release_io(struct inf_hw *hw)
646{
647	if (hw->cfg.mode) {
648		if (hw->cfg.p) {
649			release_mem_region(hw->cfg.start, hw->cfg.size);
650			iounmap(hw->cfg.p);
651		} else
652			release_region(hw->cfg.start, hw->cfg.size);
653		hw->cfg.mode = AM_NONE;
654	}
655	if (hw->addr.mode) {
656		if (hw->addr.p) {
657			release_mem_region(hw->addr.start, hw->addr.size);
658			iounmap(hw->addr.p);
659		} else
660			release_region(hw->addr.start, hw->addr.size);
661		hw->addr.mode = AM_NONE;
662	}
663}
664
665static int
666setup_io(struct inf_hw *hw)
667{
668	int err = 0;
669
670	if (hw->ci->cfg_mode) {
671		hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
672		hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
673		if (hw->ci->cfg_mode == AM_MEMIO) {
674			if (!request_mem_region(hw->cfg.start, hw->cfg.size,
675						hw->name))
676				err = -EBUSY;
677		} else {
678			if (!request_region(hw->cfg.start, hw->cfg.size,
679					    hw->name))
680				err = -EBUSY;
681		}
682		if (err) {
683			pr_info("mISDN: %s config port %lx (%lu bytes)"
684				"already in use\n", hw->name,
685				(ulong)hw->cfg.start, (ulong)hw->cfg.size);
686			return err;
687		}
688		if (hw->ci->cfg_mode == AM_MEMIO)
689			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
690		hw->cfg.mode = hw->ci->cfg_mode;
691		if (debug & DEBUG_HW)
692			pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
693				  hw->name, (ulong)hw->cfg.start,
694				  (ulong)hw->cfg.size, hw->ci->cfg_mode);
695
696	}
697	if (hw->ci->addr_mode) {
698		hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
699		hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
700		if (hw->ci->addr_mode == AM_MEMIO) {
701			if (!request_mem_region(hw->addr.start, hw->addr.size,
702						hw->name))
703				err = -EBUSY;
704		} else {
705			if (!request_region(hw->addr.start, hw->addr.size,
706					    hw->name))
707				err = -EBUSY;
708		}
709		if (err) {
710			pr_info("mISDN: %s address port %lx (%lu bytes)"
711				"already in use\n", hw->name,
712				(ulong)hw->addr.start, (ulong)hw->addr.size);
713			return err;
714		}
715		if (hw->ci->addr_mode == AM_MEMIO)
716			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
717		hw->addr.mode = hw->ci->addr_mode;
718		if (debug & DEBUG_HW)
719			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
720				  hw->name, (ulong)hw->addr.start,
721				  (ulong)hw->addr.size, hw->ci->addr_mode);
722
723	}
724
725	switch (hw->ci->typ) {
726	case INF_DIVA20:
727	case INF_DIVA20U:
728		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
729		hw->isac.mode = hw->cfg.mode;
730		hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
731		hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
732		hw->hscx.mode = hw->cfg.mode;
733		hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
734		hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
735		break;
736	case INF_DIVA201:
737		hw->ipac.type = IPAC_TYPE_IPAC;
738		hw->ipac.isac.off = 0x80;
739		hw->isac.mode = hw->addr.mode;
740		hw->isac.a.p = hw->addr.p;
741		hw->hscx.mode = hw->addr.mode;
742		hw->hscx.a.p = hw->addr.p;
743		break;
744	case INF_DIVA202:
745		hw->ipac.type = IPAC_TYPE_IPACX;
746		hw->isac.mode = hw->addr.mode;
747		hw->isac.a.p = hw->addr.p;
748		hw->hscx.mode = hw->addr.mode;
749		hw->hscx.a.p = hw->addr.p;
750		break;
751	case INF_SPEEDWIN:
752	case INF_SAPHIR3:
753		hw->ipac.type = IPAC_TYPE_IPAC;
754		hw->ipac.isac.off = 0x80;
755		hw->isac.mode = hw->cfg.mode;
756		hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
757		hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
758		hw->hscx.mode = hw->cfg.mode;
759		hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
760		hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
761		outb(0xff, (ulong)hw->cfg.start);
762		mdelay(1);
763		outb(0x00, (ulong)hw->cfg.start);
764		mdelay(1);
765		outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
766		break;
767	case INF_QS1000:
768	case INF_QS3000:
769		hw->ipac.type = IPAC_TYPE_IPAC;
770		hw->ipac.isac.off = 0x80;
771		hw->isac.a.io.ale = (u32)hw->addr.start;
772		hw->isac.a.io.port = (u32)hw->addr.start + 1;
773		hw->isac.mode = hw->addr.mode;
774		hw->hscx.a.io.ale = (u32)hw->addr.start;
775		hw->hscx.a.io.port = (u32)hw->addr.start + 1;
776		hw->hscx.mode = hw->addr.mode;
777		break;
778	case INF_NICCY:
779		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
780		hw->isac.mode = hw->addr.mode;
781		hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
782		hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
783		hw->hscx.mode = hw->addr.mode;
784		hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
785		hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
786		break;
787	case INF_SCT_1:
788		hw->ipac.type = IPAC_TYPE_IPAC;
789		hw->ipac.isac.off = 0x80;
790		hw->isac.a.io.ale = (u32)hw->addr.start;
791		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
792		hw->isac.mode = hw->addr.mode;
793		hw->hscx.a.io.ale = hw->isac.a.io.ale;
794		hw->hscx.a.io.port = hw->isac.a.io.port;
795		hw->hscx.mode = hw->addr.mode;
796		break;
797	case INF_SCT_2:
798		hw->ipac.type = IPAC_TYPE_IPAC;
799		hw->ipac.isac.off = 0x80;
800		hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
801		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
802		hw->isac.mode = hw->addr.mode;
803		hw->hscx.a.io.ale = hw->isac.a.io.ale;
804		hw->hscx.a.io.port = hw->isac.a.io.port;
805		hw->hscx.mode = hw->addr.mode;
806		break;
807	case INF_SCT_3:
808		hw->ipac.type = IPAC_TYPE_IPAC;
809		hw->ipac.isac.off = 0x80;
810		hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
811		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
812		hw->isac.mode = hw->addr.mode;
813		hw->hscx.a.io.ale = hw->isac.a.io.ale;
814		hw->hscx.a.io.port = hw->isac.a.io.port;
815		hw->hscx.mode = hw->addr.mode;
816		break;
817	case INF_SCT_4:
818		hw->ipac.type = IPAC_TYPE_IPAC;
819		hw->ipac.isac.off = 0x80;
820		hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
821		hw->isac.a.io.port = hw->isac.a.io.ale + 4;
822		hw->isac.mode = hw->addr.mode;
823		hw->hscx.a.io.ale = hw->isac.a.io.ale;
824		hw->hscx.a.io.port = hw->isac.a.io.port;
825		hw->hscx.mode = hw->addr.mode;
826		break;
827	case INF_GAZEL_R685:
828		hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
829		hw->ipac.isac.off = 0x80;
830		hw->isac.mode = hw->addr.mode;
831		hw->isac.a.io.port = (u32)hw->addr.start;
832		hw->hscx.mode = hw->addr.mode;
833		hw->hscx.a.io.port = hw->isac.a.io.port;
834		break;
835	case INF_GAZEL_R753:
836		hw->ipac.type = IPAC_TYPE_IPAC;
837		hw->ipac.isac.off = 0x80;
838		hw->isac.mode = hw->addr.mode;
839		hw->isac.a.io.ale = (u32)hw->addr.start;
840		hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
841		hw->hscx.mode = hw->addr.mode;
842		hw->hscx.a.io.ale = hw->isac.a.io.ale;
843		hw->hscx.a.io.port = hw->isac.a.io.port;
844		break;
845	default:
846		return -EINVAL;
847	}
848	switch (hw->isac.mode) {
849	case AM_MEMIO:
850		ASSIGN_FUNC_IPAC(MIO, hw->ipac);
851		break;
852	case AM_IND_IO:
853		ASSIGN_FUNC_IPAC(IND, hw->ipac);
854		break;
855	case AM_IO:
856		ASSIGN_FUNC_IPAC(IO, hw->ipac);
857		break;
858	default:
859		return -EINVAL;
860	}
861	return 0;
862}
863
864static void
865release_card(struct inf_hw *card) {
866	ulong	flags;
867	int	i;
868
869	spin_lock_irqsave(&card->lock, flags);
870	disable_hwirq(card);
871	spin_unlock_irqrestore(&card->lock, flags);
872	card->ipac.isac.release(&card->ipac.isac);
873	free_irq(card->irq, card);
874	mISDN_unregister_device(&card->ipac.isac.dch.dev);
875	release_io(card);
876	write_lock_irqsave(&card_lock, flags);
877	list_del(&card->list);
878	write_unlock_irqrestore(&card_lock, flags);
879	switch (card->ci->typ) {
880	case INF_SCT_2:
881	case INF_SCT_3:
882	case INF_SCT_4:
883		break;
884	case INF_SCT_1:
885		for (i = 0; i < 3; i++) {
886			if (card->sc[i])
887				release_card(card->sc[i]);
888			card->sc[i] = NULL;
889		}
890	default:
891		pci_disable_device(card->pdev);
892		pci_set_drvdata(card->pdev, NULL);
893		break;
894	}
895	kfree(card);
896	inf_cnt--;
897}
898
899static int
900setup_instance(struct inf_hw *card)
901{
902	int err;
903	ulong flags;
904
905	snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
906		 inf_cnt + 1);
907	write_lock_irqsave(&card_lock, flags);
908	list_add_tail(&card->list, &Cards);
909	write_unlock_irqrestore(&card_lock, flags);
910
911	_set_debug(card);
912	card->ipac.isac.name = card->name;
913	card->ipac.name = card->name;
914	card->ipac.owner = THIS_MODULE;
915	spin_lock_init(&card->lock);
916	card->ipac.isac.hwlock = &card->lock;
917	card->ipac.hwlock = &card->lock;
918	card->ipac.ctrl = (void *)&inf_ctrl;
919
920	err = setup_io(card);
921	if (err)
922		goto error_setup;
923
924	card->ipac.isac.dch.dev.Bprotocols =
925		mISDNipac_init(&card->ipac, card);
926
927	if (card->ipac.isac.dch.dev.Bprotocols == 0)
928		goto error_setup;
929
930	err = mISDN_register_device(&card->ipac.isac.dch.dev,
931				    &card->pdev->dev, card->name);
932	if (err)
933		goto error;
934
935	err = init_irq(card);
936	if (!err)  {
937		inf_cnt++;
938		pr_notice("Infineon %d cards installed\n", inf_cnt);
939		return 0;
940	}
941	mISDN_unregister_device(&card->ipac.isac.dch.dev);
942error:
943	card->ipac.release(&card->ipac);
944error_setup:
945	release_io(card);
946	write_lock_irqsave(&card_lock, flags);
947	list_del(&card->list);
948	write_unlock_irqrestore(&card_lock, flags);
949	return err;
950}
951
952static const struct inf_cinfo inf_card_info[] = {
953	{
954		INF_DIVA20,
955		"Dialogic Diva 2.0",
956		"diva20",
957		AM_IND_IO, AM_NONE, 2, 0,
958		&diva_irq
959	},
960	{
961		INF_DIVA20U,
962		"Dialogic Diva 2.0U",
963		"diva20U",
964		AM_IND_IO, AM_NONE, 2, 0,
965		&diva_irq
966	},
967	{
968		INF_DIVA201,
969		"Dialogic Diva 2.01",
970		"diva201",
971		AM_MEMIO, AM_MEMIO, 0, 1,
972		&diva20x_irq
973	},
974	{
975		INF_DIVA202,
976		"Dialogic Diva 2.02",
977		"diva202",
978		AM_MEMIO, AM_MEMIO, 0, 1,
979		&diva20x_irq
980	},
981	{
982		INF_SPEEDWIN,
983		"Sedlbauer SpeedWin PCI",
984		"speedwin",
985		AM_IND_IO, AM_NONE, 0, 0,
986		&tiger_irq
987	},
988	{
989		INF_SAPHIR3,
990		"HST Saphir 3",
991		"saphir",
992		AM_IND_IO, AM_NONE, 0, 0,
993		&tiger_irq
994	},
995	{
996		INF_QS1000,
997		"Develo Microlink PCI",
998		"qs1000",
999		AM_IO, AM_IND_IO, 1, 3,
1000		&elsa_irq
1001	},
1002	{
1003		INF_QS3000,
1004		"Develo QuickStep 3000",
1005		"qs3000",
1006		AM_IO, AM_IND_IO, 1, 3,
1007		&elsa_irq
1008	},
1009	{
1010		INF_NICCY,
1011		"Sagem NICCY",
1012		"niccy",
1013		AM_IO, AM_IND_IO, 0, 1,
1014		&niccy_irq
1015	},
1016	{
1017		INF_SCT_1,
1018		"SciTel Quadro",
1019		"p1_scitel",
1020		AM_IO, AM_IND_IO, 1, 5,
1021		&ipac_irq
1022	},
1023	{
1024		INF_SCT_2,
1025		"SciTel Quadro",
1026		"p2_scitel",
1027		AM_NONE, AM_IND_IO, 0, 4,
1028		&ipac_irq
1029	},
1030	{
1031		INF_SCT_3,
1032		"SciTel Quadro",
1033		"p3_scitel",
1034		AM_NONE, AM_IND_IO, 0, 3,
1035		&ipac_irq
1036	},
1037	{
1038		INF_SCT_4,
1039		"SciTel Quadro",
1040		"p4_scitel",
1041		AM_NONE, AM_IND_IO, 0, 2,
1042		&ipac_irq
1043	},
1044	{
1045		INF_GAZEL_R685,
1046		"Gazel R685",
1047		"gazel685",
1048		AM_IO, AM_IO, 1, 2,
1049		&gazel_irq
1050	},
1051	{
1052		INF_GAZEL_R753,
1053		"Gazel R753",
1054		"gazel753",
1055		AM_IO, AM_IND_IO, 1, 2,
1056		&ipac_irq
1057	},
1058	{
1059		INF_NONE,
1060	}
1061};
1062
1063static const struct inf_cinfo *
1064get_card_info(enum inf_types typ)
1065{
1066	const struct inf_cinfo *ci = inf_card_info;
1067
1068	while (ci->typ != INF_NONE) {
1069		if (ci->typ == typ)
1070			return ci;
1071		ci++;
1072	}
1073	return NULL;
1074}
1075
1076static int
1077inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1078{
1079	int err = -ENOMEM;
1080	struct inf_hw *card;
1081
1082	card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1083	if (!card) {
1084		pr_info("No memory for Infineon ISDN card\n");
1085		return err;
1086	}
1087	card->pdev = pdev;
1088	err = pci_enable_device(pdev);
1089	if (err) {
1090		kfree(card);
1091		return err;
1092	}
1093	card->ci = get_card_info(ent->driver_data);
1094	if (!card->ci) {
1095		pr_info("mISDN: do not have information about adapter at %s\n",
1096			pci_name(pdev));
1097		kfree(card);
1098		pci_disable_device(pdev);
1099		return -EINVAL;
1100	} else
1101		pr_notice("mISDN: found adapter %s at %s\n",
1102			  card->ci->full, pci_name(pdev));
1103
1104	card->irq = pdev->irq;
1105	pci_set_drvdata(pdev, card);
1106	err = setup_instance(card);
1107	if (err) {
1108		pci_disable_device(pdev);
1109		kfree(card);
1110		pci_set_drvdata(pdev, NULL);
1111	} else if (ent->driver_data == INF_SCT_1) {
1112		int i;
1113		struct inf_hw *sc;
1114
1115		for (i = 1; i < 4; i++) {
1116			sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1117			if (!sc) {
1118				release_card(card);
1119				pci_disable_device(pdev);
1120				return -ENOMEM;
1121			}
1122			sc->irq = card->irq;
1123			sc->pdev = card->pdev;
1124			sc->ci = card->ci + i;
1125			err = setup_instance(sc);
1126			if (err) {
1127				pci_disable_device(pdev);
1128				kfree(sc);
1129				release_card(card);
1130				break;
1131			} else
1132				card->sc[i - 1] = sc;
1133		}
1134	}
1135	return err;
1136}
1137
1138static void
1139inf_remove(struct pci_dev *pdev)
1140{
1141	struct inf_hw	*card = pci_get_drvdata(pdev);
1142
1143	if (card)
1144		release_card(card);
1145	else
1146		pr_debug("%s: drvdata already removed\n", __func__);
1147}
1148
1149static struct pci_driver infineon_driver = {
1150	.name = "ISDN Infineon pci",
1151	.probe = inf_probe,
1152	.remove = inf_remove,
1153	.id_table = infineon_ids,
1154};
1155
1156static int __init
1157infineon_init(void)
1158{
1159	int err;
1160
1161	pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1162	err = pci_register_driver(&infineon_driver);
1163	return err;
1164}
1165
1166static void __exit
1167infineon_cleanup(void)
1168{
1169	pci_unregister_driver(&infineon_driver);
1170}
1171
1172module_init(infineon_init);
1173module_exit(infineon_cleanup);
1174