]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/isdn/hardware/mISDN/mISDNinfineon.c
drivers/isdn: Remove unnecessary semicolons
[net-next-2.6.git] / drivers / isdn / hardware / mISDN / mISDNinfineon.c
CommitLineData
cae86d4a
KK
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>
5a0e3ad6 45#include <linux/slab.h>
cae86d4a
KK
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 = {
d930d1a1
PH
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 },
cae86d4a
KK
132 { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
133 PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
d930d1a1 134 INF_SPEEDWIN },
cae86d4a 135 { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
d930d1a1
PH
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 },
cae86d4a
KK
140 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
141 PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
d930d1a1
PH
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 },
cae86d4a
KK
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);
ad65ffd1 423 val |= NICCY_IRQ_ENABLE;
cae86d4a
KK
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 /* Workaround PCI9060 */
511 outb(9, (u32)hw->cfg.start + 0x69);
512 outb(DIVA_RESET_BIT | DIVA_LED_A,
513 (u32)hw->cfg.start + DIVA_PCI_CTRL);
514 break;
515 case INF_DIVA201:
516 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
517 hw->cfg.p + PITA_MISC_REG);
518 mdelay(1);
519 writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
520 mdelay(10);
521 break;
522 case INF_DIVA202:
523 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
524 hw->cfg.p + PITA_MISC_REG);
525 mdelay(1);
526 writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
527 hw->cfg.p + PITA_MISC_REG);
528 mdelay(10);
529 break;
530 case INF_SPEEDWIN:
531 case INF_SAPHIR3:
532 ipac_chip_reset(hw);
533 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
534 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
535 hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
536 break;
537 case INF_QS1000:
538 case INF_QS3000:
539 ipac_chip_reset(hw);
540 hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
541 hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
542 hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
543 break;
544 case INF_NICCY:
545 break;
546 case INF_SCT_1:
547 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
548 w &= (~SCT_PLX_RESET_BIT);
549 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
550 mdelay(10);
551 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
552 w |= SCT_PLX_RESET_BIT;
553 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
554 mdelay(10);
555 break;
556 case INF_GAZEL_R685:
557 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
558 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
559 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
560 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
561 mdelay(4);
562 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
563 mdelay(10);
564 hw->ipac.isac.adf2 = 0x87;
565 hw->ipac.hscx[0].slot = 0x1f;
4101e976 566 hw->ipac.hscx[1].slot = 0x23;
cae86d4a
KK
567 break;
568 case INF_GAZEL_R753:
569 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
570 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
571 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
572 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
573 mdelay(4);
574 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
575 mdelay(10);
576 ipac_chip_reset(hw);
577 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
578 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
579 hw->ipac.conf = 0x01; /* IOM off */
580 break;
581 default:
582 return;
583 }
584 enable_hwirq(hw);
585}
586
587static int
588inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
589{
590 int ret = 0;
591
592 switch (cmd) {
593 case HW_RESET_REQ:
594 reset_inf(hw);
595 break;
596 default:
597 pr_info("%s: %s unknown command %x %lx\n",
598 hw->name, __func__, cmd, arg);
599 ret = -EINVAL;
600 break;
601 }
602 return ret;
603}
604
605static int __devinit
606init_irq(struct inf_hw *hw)
607{
608 int ret, cnt = 3;
609 u_long flags;
610
611 if (!hw->ci->irqfunc)
612 return -EINVAL;
613 ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
614 if (ret) {
615 pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
616 return ret;
617 }
618 while (cnt--) {
619 spin_lock_irqsave(&hw->lock, flags);
620 reset_inf(hw);
621 ret = hw->ipac.init(&hw->ipac);
622 if (ret) {
623 spin_unlock_irqrestore(&hw->lock, flags);
624 pr_info("%s: ISAC init failed with %d\n",
625 hw->name, ret);
626 break;
627 }
628 spin_unlock_irqrestore(&hw->lock, flags);
629 msleep_interruptible(10);
630 if (debug & DEBUG_HW)
631 pr_notice("%s: IRQ %d count %d\n", hw->name,
632 hw->irq, hw->irqcnt);
633 if (!hw->irqcnt) {
634 pr_info("%s: IRQ(%d) got no requests during init %d\n",
635 hw->name, hw->irq, 3 - cnt);
636 } else
637 return 0;
638 }
639 free_irq(hw->irq, hw);
640 return -EIO;
641}
642
643static void
644release_io(struct inf_hw *hw)
645{
646 if (hw->cfg.mode) {
647 if (hw->cfg.p) {
648 release_mem_region(hw->cfg.start, hw->cfg.size);
649 iounmap(hw->cfg.p);
650 } else
651 release_region(hw->cfg.start, hw->cfg.size);
652 hw->cfg.mode = AM_NONE;
653 }
654 if (hw->addr.mode) {
655 if (hw->addr.p) {
656 release_mem_region(hw->addr.start, hw->addr.size);
657 iounmap(hw->addr.p);
658 } else
659 release_region(hw->addr.start, hw->addr.size);
660 hw->addr.mode = AM_NONE;
661 }
662}
663
664static int __devinit
665setup_io(struct inf_hw *hw)
666{
667 int err = 0;
668
669 if (hw->ci->cfg_mode) {
670 hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
671 hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
672 if (hw->ci->cfg_mode == AM_MEMIO) {
673 if (!request_mem_region(hw->cfg.start, hw->cfg.size,
674 hw->name))
675 err = -EBUSY;
676 } else {
677 if (!request_region(hw->cfg.start, hw->cfg.size,
678 hw->name))
679 err = -EBUSY;
680 }
681 if (err) {
682 pr_info("mISDN: %s config port %lx (%lu bytes)"
683 "already in use\n", hw->name,
684 (ulong)hw->cfg.start, (ulong)hw->cfg.size);
685 return err;
686 }
687 if (hw->ci->cfg_mode == AM_MEMIO)
688 hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
689 hw->cfg.mode = hw->ci->cfg_mode;
690 if (debug & DEBUG_HW)
691 pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
692 hw->name, (ulong)hw->cfg.start,
693 (ulong)hw->cfg.size, hw->ci->cfg_mode);
694
695 }
696 if (hw->ci->addr_mode) {
697 hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
698 hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
699 if (hw->ci->addr_mode == AM_MEMIO) {
700 if (!request_mem_region(hw->addr.start, hw->addr.size,
701 hw->name))
702 err = -EBUSY;
703 } else {
704 if (!request_region(hw->addr.start, hw->addr.size,
705 hw->name))
706 err = -EBUSY;
707 }
708 if (err) {
709 pr_info("mISDN: %s address port %lx (%lu bytes)"
710 "already in use\n", hw->name,
711 (ulong)hw->addr.start, (ulong)hw->addr.size);
712 return err;
713 }
714 if (hw->ci->addr_mode == AM_MEMIO)
715 hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
716 hw->addr.mode = hw->ci->addr_mode;
717 if (debug & DEBUG_HW)
718 pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
719 hw->name, (ulong)hw->addr.start,
720 (ulong)hw->addr.size, hw->ci->addr_mode);
721
722 }
723
724 switch (hw->ci->typ) {
725 case INF_DIVA20:
726 case INF_DIVA20U:
727 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
728 hw->isac.mode = hw->cfg.mode;
729 hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
730 hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
731 hw->hscx.mode = hw->cfg.mode;
732 hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
733 hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
734 break;
735 case INF_DIVA201:
736 hw->ipac.type = IPAC_TYPE_IPAC;
737 hw->ipac.isac.off = 0x80;
738 hw->isac.mode = hw->addr.mode;
739 hw->isac.a.p = hw->addr.p;
740 hw->hscx.mode = hw->addr.mode;
741 hw->hscx.a.p = hw->addr.p;
742 break;
743 case INF_DIVA202:
744 hw->ipac.type = IPAC_TYPE_IPACX;
745 hw->isac.mode = hw->addr.mode;
746 hw->isac.a.p = hw->addr.p;
747 hw->hscx.mode = hw->addr.mode;
748 hw->hscx.a.p = hw->addr.p;
749 break;
750 case INF_SPEEDWIN:
751 case INF_SAPHIR3:
752 hw->ipac.type = IPAC_TYPE_IPAC;
753 hw->ipac.isac.off = 0x80;
754 hw->isac.mode = hw->cfg.mode;
755 hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
756 hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
757 hw->hscx.mode = hw->cfg.mode;
758 hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
759 hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
760 outb(0xff, (ulong)hw->cfg.start);
761 mdelay(1);
762 outb(0x00, (ulong)hw->cfg.start);
763 mdelay(1);
764 outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
765 break;
766 case INF_QS1000:
767 case INF_QS3000:
768 hw->ipac.type = IPAC_TYPE_IPAC;
769 hw->ipac.isac.off = 0x80;
770 hw->isac.a.io.ale = (u32)hw->addr.start;
771 hw->isac.a.io.port = (u32)hw->addr.start + 1;
772 hw->isac.mode = hw->addr.mode;
773 hw->hscx.a.io.ale = (u32)hw->addr.start;
774 hw->hscx.a.io.port = (u32)hw->addr.start + 1;
775 hw->hscx.mode = hw->addr.mode;
776 break;
777 case INF_NICCY:
778 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
779 hw->isac.mode = hw->addr.mode;
780 hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
781 hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
782 hw->hscx.mode = hw->addr.mode;
783 hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
784 hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
785 break;
786 case INF_SCT_1:
787 hw->ipac.type = IPAC_TYPE_IPAC;
788 hw->ipac.isac.off = 0x80;
789 hw->isac.a.io.ale = (u32)hw->addr.start;
790 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
791 hw->isac.mode = hw->addr.mode;
792 hw->hscx.a.io.ale = hw->isac.a.io.ale;
793 hw->hscx.a.io.port = hw->isac.a.io.port;
794 hw->hscx.mode = hw->addr.mode;
795 break;
796 case INF_SCT_2:
797 hw->ipac.type = IPAC_TYPE_IPAC;
798 hw->ipac.isac.off = 0x80;
799 hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
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_3:
807 hw->ipac.type = IPAC_TYPE_IPAC;
808 hw->ipac.isac.off = 0x80;
809 hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
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_4:
817 hw->ipac.type = IPAC_TYPE_IPAC;
818 hw->ipac.isac.off = 0x80;
819 hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
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_GAZEL_R685:
827 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
828 hw->ipac.isac.off = 0x80;
829 hw->isac.mode = hw->addr.mode;
830 hw->isac.a.io.port = (u32)hw->addr.start;
831 hw->hscx.mode = hw->addr.mode;
832 hw->hscx.a.io.port = hw->isac.a.io.port;
833 break;
834 case INF_GAZEL_R753:
835 hw->ipac.type = IPAC_TYPE_IPAC;
836 hw->ipac.isac.off = 0x80;
837 hw->isac.mode = hw->addr.mode;
838 hw->isac.a.io.ale = (u32)hw->addr.start;
839 hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
840 hw->hscx.mode = hw->addr.mode;
841 hw->hscx.a.io.ale = hw->isac.a.io.ale;
842 hw->hscx.a.io.port = hw->isac.a.io.port;
843 break;
844 default:
845 return -EINVAL;
846 }
847 switch (hw->isac.mode) {
848 case AM_MEMIO:
849 ASSIGN_FUNC_IPAC(MIO, hw->ipac);
850 break;
851 case AM_IND_IO:
852 ASSIGN_FUNC_IPAC(IND, hw->ipac);
853 break;
854 case AM_IO:
855 ASSIGN_FUNC_IPAC(IO, hw->ipac);
856 break;
857 default:
858 return -EINVAL;
859 }
860 return 0;
861}
862
863static void
864release_card(struct inf_hw *card) {
865 ulong flags;
866 int i;
867
868 spin_lock_irqsave(&card->lock, flags);
869 disable_hwirq(card);
870 spin_unlock_irqrestore(&card->lock, flags);
871 card->ipac.isac.release(&card->ipac.isac);
872 free_irq(card->irq, card);
873 mISDN_unregister_device(&card->ipac.isac.dch.dev);
874 release_io(card);
875 write_lock_irqsave(&card_lock, flags);
876 list_del(&card->list);
877 write_unlock_irqrestore(&card_lock, flags);
878 switch (card->ci->typ) {
879 case INF_SCT_2:
880 case INF_SCT_3:
881 case INF_SCT_4:
882 break;
883 case INF_SCT_1:
884 for (i = 0; i < 3; i++) {
885 if (card->sc[i])
886 release_card(card->sc[i]);
887 card->sc[i] = NULL;
888 }
889 default:
890 pci_disable_device(card->pdev);
891 pci_set_drvdata(card->pdev, NULL);
892 break;
893 }
894 kfree(card);
895 inf_cnt--;
896}
897
898static int __devinit
899setup_instance(struct inf_hw *card)
900{
901 int err;
902 ulong flags;
903
904 snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
905 inf_cnt + 1);
906 write_lock_irqsave(&card_lock, flags);
907 list_add_tail(&card->list, &Cards);
908 write_unlock_irqrestore(&card_lock, flags);
909
910 _set_debug(card);
911 card->ipac.isac.name = card->name;
912 card->ipac.name = card->name;
913 card->ipac.owner = THIS_MODULE;
914 spin_lock_init(&card->lock);
915 card->ipac.isac.hwlock = &card->lock;
916 card->ipac.hwlock = &card->lock;
917 card->ipac.ctrl = (void *)&inf_ctrl;
918
919 err = setup_io(card);
920 if (err)
921 goto error_setup;
922
923 card->ipac.isac.dch.dev.Bprotocols =
924 mISDNipac_init(&card->ipac, card);
925
926 if (card->ipac.isac.dch.dev.Bprotocols == 0)
ad65ffd1 927 goto error_setup;
cae86d4a
KK
928
929 err = mISDN_register_device(&card->ipac.isac.dch.dev,
930 &card->pdev->dev, card->name);
931 if (err)
932 goto error;
933
934 err = init_irq(card);
935 if (!err) {
936 inf_cnt++;
937 pr_notice("Infineon %d cards installed\n", inf_cnt);
938 return 0;
939 }
940 mISDN_unregister_device(&card->ipac.isac.dch.dev);
941error:
942 card->ipac.release(&card->ipac);
943error_setup:
944 release_io(card);
945 write_lock_irqsave(&card_lock, flags);
946 list_del(&card->list);
947 write_unlock_irqrestore(&card_lock, flags);
948 return err;
949}
950
951static const struct inf_cinfo inf_card_info[] = {
952 {
953 INF_DIVA20,
954 "Dialogic Diva 2.0",
955 "diva20",
956 AM_IND_IO, AM_NONE, 2, 0,
957 &diva_irq
958 },
959 {
960 INF_DIVA20U,
961 "Dialogic Diva 2.0U",
962 "diva20U",
963 AM_IND_IO, AM_NONE, 2, 0,
964 &diva_irq
965 },
966 {
967 INF_DIVA201,
968 "Dialogic Diva 2.01",
969 "diva201",
970 AM_MEMIO, AM_MEMIO, 0, 1,
971 &diva20x_irq
972 },
973 {
974 INF_DIVA202,
975 "Dialogic Diva 2.02",
976 "diva202",
977 AM_MEMIO, AM_MEMIO, 0, 1,
978 &diva20x_irq
979 },
980 {
981 INF_SPEEDWIN,
982 "Sedlbauer SpeedWin PCI",
983 "speedwin",
984 AM_IND_IO, AM_NONE, 0, 0,
985 &tiger_irq
986 },
987 {
988 INF_SAPHIR3,
989 "HST Saphir 3",
990 "saphir",
991 AM_IND_IO, AM_NONE, 0, 0,
992 &tiger_irq
993 },
994 {
995 INF_QS1000,
996 "Develo Microlink PCI",
997 "qs1000",
998 AM_IO, AM_IND_IO, 1, 3,
999 &elsa_irq
1000 },
1001 {
1002 INF_QS3000,
1003 "Develo QuickStep 3000",
1004 "qs3000",
1005 AM_IO, AM_IND_IO, 1, 3,
1006 &elsa_irq
1007 },
1008 {
1009 INF_NICCY,
1010 "Sagem NICCY",
1011 "niccy",
1012 AM_IO, AM_IND_IO, 0, 1,
1013 &niccy_irq
1014 },
1015 {
1016 INF_SCT_1,
1017 "SciTel Quadro",
1018 "p1_scitel",
1019 AM_IO, AM_IND_IO, 1, 5,
1020 &ipac_irq
1021 },
1022 {
1023 INF_SCT_2,
1024 "SciTel Quadro",
1025 "p2_scitel",
1026 AM_NONE, AM_IND_IO, 0, 4,
1027 &ipac_irq
1028 },
1029 {
1030 INF_SCT_3,
1031 "SciTel Quadro",
1032 "p3_scitel",
1033 AM_NONE, AM_IND_IO, 0, 3,
1034 &ipac_irq
1035 },
1036 {
1037 INF_SCT_4,
1038 "SciTel Quadro",
1039 "p4_scitel",
1040 AM_NONE, AM_IND_IO, 0, 2,
1041 &ipac_irq
1042 },
1043 {
1044 INF_GAZEL_R685,
1045 "Gazel R685",
1046 "gazel685",
1047 AM_IO, AM_IO, 1, 2,
1048 &gazel_irq
1049 },
1050 {
1051 INF_GAZEL_R753,
1052 "Gazel R753",
1053 "gazel753",
1054 AM_IO, AM_IND_IO, 1, 2,
1055 &ipac_irq
1056 },
1057 {
1058 INF_NONE,
1059 }
1060};
1061
1062static const struct inf_cinfo * __devinit
1063get_card_info(enum inf_types typ)
1064{
1065 const struct inf_cinfo *ci = inf_card_info;
1066
1067 while (ci->typ != INF_NONE) {
1068 if (ci->typ == typ)
1069 return ci;
1070 ci++;
1071 }
1072 return NULL;
1073}
1074
1075static int __devinit
1076inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1077{
1078 int err = -ENOMEM;
1079 struct inf_hw *card;
1080
1081 card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1082 if (!card) {
1083 pr_info("No memory for Infineon ISDN card\n");
1084 return err;
1085 }
1086 card->pdev = pdev;
1087 err = pci_enable_device(pdev);
1088 if (err) {
1089 kfree(card);
1090 return err;
1091 }
1092 card->ci = get_card_info(ent->driver_data);
1093 if (!card->ci) {
1094 pr_info("mISDN: do not have informations about adapter at %s\n",
1095 pci_name(pdev));
1096 kfree(card);
06d88e4a 1097 pci_disable_device(pdev);
cae86d4a
KK
1098 return -EINVAL;
1099 } else
1100 pr_notice("mISDN: found adapter %s at %s\n",
1101 card->ci->full, pci_name(pdev));
1102
1103 card->irq = pdev->irq;
1104 pci_set_drvdata(pdev, card);
1105 err = setup_instance(card);
1106 if (err) {
06d88e4a 1107 pci_disable_device(pdev);
cae86d4a
KK
1108 kfree(card);
1109 pci_set_drvdata(pdev, NULL);
1110 } else if (ent->driver_data == INF_SCT_1) {
1111 int i;
1112 struct inf_hw *sc;
1113
1114 for (i = 1; i < 4; i++) {
1115 sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1116 if (!sc) {
1117 release_card(card);
06d88e4a 1118 pci_disable_device(pdev);
cae86d4a
KK
1119 return -ENOMEM;
1120 }
1121 sc->irq = card->irq;
1122 sc->pdev = card->pdev;
1123 sc->ci = card->ci + i;
1124 err = setup_instance(sc);
1125 if (err) {
06d88e4a 1126 pci_disable_device(pdev);
cae86d4a
KK
1127 kfree(sc);
1128 release_card(card);
f0f4d641 1129 break;
cae86d4a
KK
1130 } else
1131 card->sc[i - 1] = sc;
1132 }
1133 }
1134 return err;
1135}
1136
1137static void __devexit
1138inf_remove(struct pci_dev *pdev)
1139{
1140 struct inf_hw *card = pci_get_drvdata(pdev);
1141
1142 if (card)
1143 release_card(card);
1144 else
698f9315 1145 pr_debug("%s: drvdata already removed\n", __func__);
cae86d4a
KK
1146}
1147
1148static struct pci_driver infineon_driver = {
1149 .name = "ISDN Infineon pci",
1150 .probe = inf_probe,
1151 .remove = __devexit_p(inf_remove),
1152 .id_table = infineon_ids,
1153};
1154
1155static int __init
1156infineon_init(void)
1157{
1158 int err;
1159
1160 pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1161 err = pci_register_driver(&infineon_driver);
1162 return err;
1163}
1164
1165static void __exit
1166infineon_cleanup(void)
1167{
1168 pci_unregister_driver(&infineon_driver);
1169}
1170
1171module_init(infineon_init);
1172module_exit(infineon_cleanup);