Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/hardware/mISDN/mISDNinfineon.c
15112 views
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 <[email protected]>
23
*
24
* Copyright 2009 by Karsten Keil <[email protected]>
25
*
26
* This program is free software; you can redistribute it and/or modify
27
* it under the terms of the GNU General Public License version 2 as
28
* published by the Free Software Foundation.
29
*
30
* This program is distributed in the hope that it will be useful,
31
* but WITHOUT ANY WARRANTY; without even the implied warranty of
32
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33
* GNU General Public License for more details.
34
*
35
* You should have received a copy of the GNU General Public License
36
* along with this program; if not, write to the Free Software
37
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38
*
39
*/
40
41
#include <linux/module.h>
42
#include <linux/pci.h>
43
#include <linux/delay.h>
44
#include <linux/mISDNhw.h>
45
#include <linux/slab.h>
46
#include "ipac.h"
47
48
#define INFINEON_REV "1.0"
49
50
static int inf_cnt;
51
static u32 debug;
52
static u32 irqloops = 4;
53
54
enum 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
73
enum addr_mode {
74
AM_NONE = 0,
75
AM_IO,
76
AM_MEMIO,
77
AM_IND_IO,
78
};
79
80
struct 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
91
struct _ioaddr {
92
enum addr_mode mode;
93
union {
94
void __iomem *p;
95
struct _ioport io;
96
} a;
97
};
98
99
struct _iohandle {
100
enum addr_mode mode;
101
resource_size_t size;
102
resource_size_t start;
103
void __iomem *p;
104
};
105
106
struct 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
127
static struct pci_device_id infineon_ids[] __devinitdata = {
128
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 },
129
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U },
130
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 },
131
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA202), INF_DIVA202 },
132
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
133
PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
134
INF_SPEEDWIN },
135
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
136
PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3 },
137
{ PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_MICROLINK), INF_QS1000 },
138
{ PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_QS3000), INF_QS3000 },
139
{ PCI_VDEVICE(SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY), INF_NICCY },
140
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
141
PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
142
INF_SCT_1 },
143
{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R685), INF_GAZEL_R685 },
144
{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R753), INF_GAZEL_R753 },
145
{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO), INF_GAZEL_R753 },
146
{ PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_OLITEC), INF_GAZEL_R753 },
147
{ }
148
};
149
MODULE_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
234
static LIST_HEAD(Cards);
235
static DEFINE_RWLOCK(card_lock); /* protect Cards */
236
237
static 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
245
static int
246
set_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
261
MODULE_AUTHOR("Karsten Keil");
262
MODULE_LICENSE("GPL v2");
263
MODULE_VERSION(INFINEON_REV);
264
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
265
MODULE_PARM_DESC(debug, "infineon debug mask");
266
module_param(irqloops, uint, S_IRUGO | S_IWUSR);
267
MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
268
269
/* Interface functions */
270
271
IOFUNC_IO(ISAC, inf_hw, isac.a.io)
272
IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
273
IOFUNC_IND(ISAC, inf_hw, isac.a.io)
274
IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
275
IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
276
IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
277
278
static irqreturn_t
279
diva_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
296
static irqreturn_t
297
diva20x_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
315
static irqreturn_t
316
tiger_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
333
static irqreturn_t
334
elsa_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
351
static irqreturn_t
352
niccy_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
370
static irqreturn_t
371
gazel_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
382
static irqreturn_t
383
ipac_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
400
static void
401
enable_hwirq(struct inf_hw *hw)
402
{
403
u16 w;
404
u32 val;
405
406
switch (hw->ci->typ) {
407
case INF_DIVA201:
408
case INF_DIVA202:
409
writel(PITA_INT0_ENABLE, hw->cfg.p);
410
break;
411
case INF_SPEEDWIN:
412
case INF_SAPHIR3:
413
outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
414
break;
415
case INF_QS1000:
416
outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
417
break;
418
case INF_QS3000:
419
outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
420
break;
421
case INF_NICCY:
422
val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
423
val |= NICCY_IRQ_ENABLE;
424
outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
425
break;
426
case INF_SCT_1:
427
w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
428
w |= SCT_PLX_IRQ_ENABLE;
429
outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
430
break;
431
case INF_GAZEL_R685:
432
outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
433
(u32)hw->cfg.start + GAZEL_INCSR);
434
break;
435
case INF_GAZEL_R753:
436
outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
437
(u32)hw->cfg.start + GAZEL_INCSR);
438
break;
439
default:
440
break;
441
}
442
}
443
444
static void
445
disable_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
484
static void
485
ipac_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
495
static void
496
reset_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;
566
hw->ipac.hscx[1].slot = 0x23;
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
587
static int
588
inf_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
605
static int __devinit
606
init_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
643
static void
644
release_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
664
static int __devinit
665
setup_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
863
static void
864
release_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
898
static int __devinit
899
setup_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)
927
goto error_setup;
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);
941
error:
942
card->ipac.release(&card->ipac);
943
error_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
951
static 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
1062
static const struct inf_cinfo * __devinit
1063
get_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
1075
static int __devinit
1076
inf_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);
1097
pci_disable_device(pdev);
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) {
1107
pci_disable_device(pdev);
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);
1118
pci_disable_device(pdev);
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) {
1126
pci_disable_device(pdev);
1127
kfree(sc);
1128
release_card(card);
1129
break;
1130
} else
1131
card->sc[i - 1] = sc;
1132
}
1133
}
1134
return err;
1135
}
1136
1137
static void __devexit
1138
inf_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
1145
pr_debug("%s: drvdata already removed\n", __func__);
1146
}
1147
1148
static 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
1155
static int __init
1156
infineon_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
1165
static void __exit
1166
infineon_cleanup(void)
1167
{
1168
pci_unregister_driver(&infineon_driver);
1169
}
1170
1171
module_init(infineon_init);
1172
module_exit(infineon_cleanup);
1173
1174