blob: 62441ba53b95c1b033a7744805c9d535eda722c1 [file] [log] [blame]
Karsten Keilcae86d42009-07-22 19:42:46 +02001/*
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
49static int inf_cnt;
50static u32 debug;
51static u32 irqloops = 4;
52
53enum 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
72enum addr_mode {
73 AM_NONE = 0,
74 AM_IO,
75 AM_MEMIO,
76 AM_IND_IO,
77};
78
79struct 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
90struct _ioaddr {
91 enum addr_mode mode;
92 union {
93 void __iomem *p;
94 struct _ioport io;
95 } a;
96};
97
98struct _iohandle {
99 enum addr_mode mode;
100 resource_size_t size;
101 resource_size_t start;
102 void __iomem *p;
103};
104
105struct 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
126static 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};
159MODULE_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
244static LIST_HEAD(Cards);
245static DEFINE_RWLOCK(card_lock); /* protect Cards */
246
247static 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
255static int
256set_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
271MODULE_AUTHOR("Karsten Keil");
272MODULE_LICENSE("GPL v2");
273MODULE_VERSION(INFINEON_REV);
274module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
275MODULE_PARM_DESC(debug, "infineon debug mask");
276module_param(irqloops, uint, S_IRUGO | S_IWUSR);
277MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
278
279/* Interface functions */
280
281IOFUNC_IO(ISAC, inf_hw, isac.a.io)
282IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
283IOFUNC_IND(ISAC, inf_hw, isac.a.io)
284IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
285IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
286IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
287
288static irqreturn_t
289diva_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
306static irqreturn_t
307diva20x_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
325static irqreturn_t
326tiger_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
343static irqreturn_t
344elsa_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
361static irqreturn_t
362niccy_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
380static irqreturn_t
381gazel_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
392static irqreturn_t
393ipac_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
410static void
411enable_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
454static void
455disable_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
494static void
495ipac_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
505static void
506reset_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
597static int
598inf_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
615static int __devinit
616init_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
653static void
654release_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
674static int __devinit
675setup_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
873static void
874release_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
908static int __devinit
909setup_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);
951error:
952 card->ipac.release(&card->ipac);
953error_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
961static 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
1072static const struct inf_cinfo * __devinit
1073get_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
1085static int __devinit
1086inf_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 } else
1137 card->sc[i - 1] = sc;
1138 }
1139 }
1140 return err;
1141}
1142
1143static void __devexit
1144inf_remove(struct pci_dev *pdev)
1145{
1146 struct inf_hw *card = pci_get_drvdata(pdev);
1147
1148 if (card)
1149 release_card(card);
1150 else
1151 pr_debug("%s: drvdata allready removed\n", __func__);
1152}
1153
1154static struct pci_driver infineon_driver = {
1155 .name = "ISDN Infineon pci",
1156 .probe = inf_probe,
1157 .remove = __devexit_p(inf_remove),
1158 .id_table = infineon_ids,
1159};
1160
1161static int __init
1162infineon_init(void)
1163{
1164 int err;
1165
1166 pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1167 err = pci_register_driver(&infineon_driver);
1168 return err;
1169}
1170
1171static void __exit
1172infineon_cleanup(void)
1173{
1174 pci_unregister_driver(&infineon_driver);
1175}
1176
1177module_init(infineon_init);
1178module_exit(infineon_cleanup);