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