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