Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/hardware/mISDN/speedfax.c
15112 views
1
/*
2
* speedfax.c low level stuff for Sedlbauer Speedfax+ cards
3
* based on the ISAR DSP
4
* Thanks to Sedlbauer AG for informations and HW
5
*
6
* Author Karsten Keil <[email protected]>
7
*
8
* Copyright 2009 by Karsten Keil <[email protected]>
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2 as
12
* published by the Free Software Foundation.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
*
23
*/
24
25
#include <linux/module.h>
26
#include <linux/slab.h>
27
#include <linux/pci.h>
28
#include <linux/delay.h>
29
#include <linux/mISDNhw.h>
30
#include <linux/firmware.h>
31
#include "ipac.h"
32
#include "isar.h"
33
34
#define SPEEDFAX_REV "2.0"
35
36
#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
37
#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
38
#define PCI_SUB_ID_SEDLBAUER 0x01
39
40
#define SFAX_PCI_ADDR 0xc8
41
#define SFAX_PCI_ISAC 0xd0
42
#define SFAX_PCI_ISAR 0xe0
43
44
/* TIGER 100 Registers */
45
46
#define TIGER_RESET_ADDR 0x00
47
#define TIGER_EXTERN_RESET_ON 0x01
48
#define TIGER_EXTERN_RESET_OFF 0x00
49
#define TIGER_AUX_CTRL 0x02
50
#define TIGER_AUX_DATA 0x03
51
#define TIGER_AUX_IRQMASK 0x05
52
#define TIGER_AUX_STATUS 0x07
53
54
/* Tiger AUX BITs */
55
#define SFAX_AUX_IOMASK 0xdd /* 1 and 5 are inputs */
56
#define SFAX_ISAR_RESET_BIT_OFF 0x00
57
#define SFAX_ISAR_RESET_BIT_ON 0x01
58
#define SFAX_TIGER_IRQ_BIT 0x02
59
#define SFAX_LED1_BIT 0x08
60
#define SFAX_LED2_BIT 0x10
61
62
#define SFAX_PCI_RESET_ON (SFAX_ISAR_RESET_BIT_ON)
63
#define SFAX_PCI_RESET_OFF (SFAX_LED1_BIT | SFAX_LED2_BIT)
64
65
static int sfax_cnt;
66
static u32 debug;
67
static u32 irqloops = 4;
68
69
struct sfax_hw {
70
struct list_head list;
71
struct pci_dev *pdev;
72
char name[MISDN_MAX_IDLEN];
73
u32 irq;
74
u32 irqcnt;
75
u32 cfg;
76
struct _ioport p_isac;
77
struct _ioport p_isar;
78
u8 aux_data;
79
spinlock_t lock; /* HW access lock */
80
struct isac_hw isac;
81
struct isar_hw isar;
82
};
83
84
static LIST_HEAD(Cards);
85
static DEFINE_RWLOCK(card_lock); /* protect Cards */
86
87
static void
88
_set_debug(struct sfax_hw *card)
89
{
90
card->isac.dch.debug = debug;
91
card->isar.ch[0].bch.debug = debug;
92
card->isar.ch[1].bch.debug = debug;
93
}
94
95
static int
96
set_debug(const char *val, struct kernel_param *kp)
97
{
98
int ret;
99
struct sfax_hw *card;
100
101
ret = param_set_uint(val, kp);
102
if (!ret) {
103
read_lock(&card_lock);
104
list_for_each_entry(card, &Cards, list)
105
_set_debug(card);
106
read_unlock(&card_lock);
107
}
108
return ret;
109
}
110
111
MODULE_AUTHOR("Karsten Keil");
112
MODULE_LICENSE("GPL v2");
113
MODULE_VERSION(SPEEDFAX_REV);
114
MODULE_FIRMWARE("isdn/ISAR.BIN");
115
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
116
MODULE_PARM_DESC(debug, "Speedfax debug mask");
117
module_param(irqloops, uint, S_IRUGO | S_IWUSR);
118
MODULE_PARM_DESC(irqloops, "Speedfax maximal irqloops (default 4)");
119
120
IOFUNC_IND(ISAC, sfax_hw, p_isac)
121
IOFUNC_IND(ISAR, sfax_hw, p_isar)
122
123
static irqreturn_t
124
speedfax_irq(int intno, void *dev_id)
125
{
126
struct sfax_hw *sf = dev_id;
127
u8 val;
128
int cnt = irqloops;
129
130
spin_lock(&sf->lock);
131
val = inb(sf->cfg + TIGER_AUX_STATUS);
132
if (val & SFAX_TIGER_IRQ_BIT) { /* for us or shared ? */
133
spin_unlock(&sf->lock);
134
return IRQ_NONE; /* shared */
135
}
136
sf->irqcnt++;
137
val = ReadISAR_IND(sf, ISAR_IRQBIT);
138
Start_ISAR:
139
if (val & ISAR_IRQSTA)
140
mISDNisar_irq(&sf->isar);
141
val = ReadISAC_IND(sf, ISAC_ISTA);
142
if (val)
143
mISDNisac_irq(&sf->isac, val);
144
val = ReadISAR_IND(sf, ISAR_IRQBIT);
145
if ((val & ISAR_IRQSTA) && cnt--)
146
goto Start_ISAR;
147
if (cnt < irqloops)
148
pr_debug("%s: %d irqloops cpu%d\n", sf->name,
149
irqloops - cnt, smp_processor_id());
150
if (irqloops && !cnt)
151
pr_notice("%s: %d IRQ LOOP cpu%d\n", sf->name,
152
irqloops, smp_processor_id());
153
spin_unlock(&sf->lock);
154
return IRQ_HANDLED;
155
}
156
157
static void
158
enable_hwirq(struct sfax_hw *sf)
159
{
160
WriteISAC_IND(sf, ISAC_MASK, 0);
161
WriteISAR_IND(sf, ISAR_IRQBIT, ISAR_IRQMSK);
162
outb(SFAX_TIGER_IRQ_BIT, sf->cfg + TIGER_AUX_IRQMASK);
163
}
164
165
static void
166
disable_hwirq(struct sfax_hw *sf)
167
{
168
WriteISAC_IND(sf, ISAC_MASK, 0xFF);
169
WriteISAR_IND(sf, ISAR_IRQBIT, 0);
170
outb(0, sf->cfg + TIGER_AUX_IRQMASK);
171
}
172
173
static void
174
reset_speedfax(struct sfax_hw *sf)
175
{
176
177
pr_debug("%s: resetting card\n", sf->name);
178
outb(TIGER_EXTERN_RESET_ON, sf->cfg + TIGER_RESET_ADDR);
179
outb(SFAX_PCI_RESET_ON, sf->cfg + TIGER_AUX_DATA);
180
mdelay(1);
181
outb(TIGER_EXTERN_RESET_OFF, sf->cfg + TIGER_RESET_ADDR);
182
sf->aux_data = SFAX_PCI_RESET_OFF;
183
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
184
mdelay(1);
185
}
186
187
static int
188
sfax_ctrl(struct sfax_hw *sf, u32 cmd, u_long arg)
189
{
190
int ret = 0;
191
192
switch (cmd) {
193
case HW_RESET_REQ:
194
reset_speedfax(sf);
195
break;
196
case HW_ACTIVATE_IND:
197
if (arg & 1)
198
sf->aux_data &= ~SFAX_LED1_BIT;
199
if (arg & 2)
200
sf->aux_data &= ~SFAX_LED2_BIT;
201
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
202
break;
203
case HW_DEACT_IND:
204
if (arg & 1)
205
sf->aux_data |= SFAX_LED1_BIT;
206
if (arg & 2)
207
sf->aux_data |= SFAX_LED2_BIT;
208
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
209
break;
210
default:
211
pr_info("%s: %s unknown command %x %lx\n",
212
sf->name, __func__, cmd, arg);
213
ret = -EINVAL;
214
break;
215
}
216
return ret;
217
}
218
219
static int
220
channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
221
{
222
int ret = 0;
223
224
switch (cq->op) {
225
case MISDN_CTRL_GETOP:
226
cq->op = MISDN_CTRL_LOOP;
227
break;
228
case MISDN_CTRL_LOOP:
229
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
230
if (cq->channel < 0 || cq->channel > 3) {
231
ret = -EINVAL;
232
break;
233
}
234
ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
235
break;
236
default:
237
pr_info("%s: unknown Op %x\n", sf->name, cq->op);
238
ret = -EINVAL;
239
break;
240
}
241
return ret;
242
}
243
244
static int
245
sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
246
{
247
struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
248
struct dchannel *dch = container_of(dev, struct dchannel, dev);
249
struct sfax_hw *sf = dch->hw;
250
struct channel_req *rq;
251
int err = 0;
252
253
pr_debug("%s: cmd:%x %p\n", sf->name, cmd, arg);
254
switch (cmd) {
255
case OPEN_CHANNEL:
256
rq = arg;
257
if (rq->protocol == ISDN_P_TE_S0)
258
err = sf->isac.open(&sf->isac, rq);
259
else
260
err = sf->isar.open(&sf->isar, rq);
261
if (err)
262
break;
263
if (!try_module_get(THIS_MODULE))
264
pr_info("%s: cannot get module\n", sf->name);
265
break;
266
case CLOSE_CHANNEL:
267
pr_debug("%s: dev(%d) close from %p\n", sf->name,
268
dch->dev.id, __builtin_return_address(0));
269
module_put(THIS_MODULE);
270
break;
271
case CONTROL_CHANNEL:
272
err = channel_ctrl(sf, arg);
273
break;
274
default:
275
pr_debug("%s: unknown command %x\n", sf->name, cmd);
276
return -EINVAL;
277
}
278
return err;
279
}
280
281
static int __devinit
282
init_card(struct sfax_hw *sf)
283
{
284
int ret, cnt = 3;
285
u_long flags;
286
287
ret = request_irq(sf->irq, speedfax_irq, IRQF_SHARED, sf->name, sf);
288
if (ret) {
289
pr_info("%s: couldn't get interrupt %d\n", sf->name, sf->irq);
290
return ret;
291
}
292
while (cnt--) {
293
spin_lock_irqsave(&sf->lock, flags);
294
ret = sf->isac.init(&sf->isac);
295
if (ret) {
296
spin_unlock_irqrestore(&sf->lock, flags);
297
pr_info("%s: ISAC init failed with %d\n",
298
sf->name, ret);
299
break;
300
}
301
enable_hwirq(sf);
302
/* RESET Receiver and Transmitter */
303
WriteISAC_IND(sf, ISAC_CMDR, 0x41);
304
spin_unlock_irqrestore(&sf->lock, flags);
305
msleep_interruptible(10);
306
if (debug & DEBUG_HW)
307
pr_notice("%s: IRQ %d count %d\n", sf->name,
308
sf->irq, sf->irqcnt);
309
if (!sf->irqcnt) {
310
pr_info("%s: IRQ(%d) got no requests during init %d\n",
311
sf->name, sf->irq, 3 - cnt);
312
} else
313
return 0;
314
}
315
free_irq(sf->irq, sf);
316
return -EIO;
317
}
318
319
320
static int __devinit
321
setup_speedfax(struct sfax_hw *sf)
322
{
323
u_long flags;
324
325
if (!request_region(sf->cfg, 256, sf->name)) {
326
pr_info("mISDN: %s config port %x-%x already in use\n",
327
sf->name, sf->cfg, sf->cfg + 255);
328
return -EIO;
329
}
330
outb(0xff, sf->cfg);
331
outb(0, sf->cfg);
332
outb(0xdd, sf->cfg + TIGER_AUX_CTRL);
333
outb(0, sf->cfg + TIGER_AUX_IRQMASK);
334
335
sf->isac.type = IPAC_TYPE_ISAC;
336
sf->p_isac.ale = sf->cfg + SFAX_PCI_ADDR;
337
sf->p_isac.port = sf->cfg + SFAX_PCI_ISAC;
338
sf->p_isar.ale = sf->cfg + SFAX_PCI_ADDR;
339
sf->p_isar.port = sf->cfg + SFAX_PCI_ISAR;
340
ASSIGN_FUNC(IND, ISAC, sf->isac);
341
ASSIGN_FUNC(IND, ISAR, sf->isar);
342
spin_lock_irqsave(&sf->lock, flags);
343
reset_speedfax(sf);
344
disable_hwirq(sf);
345
spin_unlock_irqrestore(&sf->lock, flags);
346
return 0;
347
}
348
349
static void
350
release_card(struct sfax_hw *card) {
351
u_long flags;
352
353
spin_lock_irqsave(&card->lock, flags);
354
disable_hwirq(card);
355
spin_unlock_irqrestore(&card->lock, flags);
356
card->isac.release(&card->isac);
357
free_irq(card->irq, card);
358
card->isar.release(&card->isar);
359
mISDN_unregister_device(&card->isac.dch.dev);
360
release_region(card->cfg, 256);
361
pci_disable_device(card->pdev);
362
pci_set_drvdata(card->pdev, NULL);
363
write_lock_irqsave(&card_lock, flags);
364
list_del(&card->list);
365
write_unlock_irqrestore(&card_lock, flags);
366
kfree(card);
367
sfax_cnt--;
368
}
369
370
static int __devinit
371
setup_instance(struct sfax_hw *card)
372
{
373
const struct firmware *firmware;
374
int i, err;
375
u_long flags;
376
377
snprintf(card->name, MISDN_MAX_IDLEN - 1, "Speedfax.%d", sfax_cnt + 1);
378
write_lock_irqsave(&card_lock, flags);
379
list_add_tail(&card->list, &Cards);
380
write_unlock_irqrestore(&card_lock, flags);
381
_set_debug(card);
382
spin_lock_init(&card->lock);
383
card->isac.hwlock = &card->lock;
384
card->isar.hwlock = &card->lock;
385
card->isar.ctrl = (void *)&sfax_ctrl;
386
card->isac.name = card->name;
387
card->isar.name = card->name;
388
card->isar.owner = THIS_MODULE;
389
390
err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev);
391
if (err < 0) {
392
pr_info("%s: firmware request failed %d\n",
393
card->name, err);
394
goto error_fw;
395
}
396
if (debug & DEBUG_HW)
397
pr_notice("%s: got firmware %zu bytes\n",
398
card->name, firmware->size);
399
400
mISDNisac_init(&card->isac, card);
401
402
card->isac.dch.dev.D.ctrl = sfax_dctrl;
403
card->isac.dch.dev.Bprotocols =
404
mISDNisar_init(&card->isar, card);
405
for (i = 0; i < 2; i++) {
406
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
407
list_add(&card->isar.ch[i].bch.ch.list,
408
&card->isac.dch.dev.bchannels);
409
}
410
411
err = setup_speedfax(card);
412
if (err)
413
goto error_setup;
414
err = card->isar.init(&card->isar);
415
if (err)
416
goto error;
417
err = mISDN_register_device(&card->isac.dch.dev,
418
&card->pdev->dev, card->name);
419
if (err)
420
goto error;
421
err = init_card(card);
422
if (err)
423
goto error_init;
424
err = card->isar.firmware(&card->isar, firmware->data, firmware->size);
425
if (!err) {
426
release_firmware(firmware);
427
sfax_cnt++;
428
pr_notice("SpeedFax %d cards installed\n", sfax_cnt);
429
return 0;
430
}
431
disable_hwirq(card);
432
free_irq(card->irq, card);
433
error_init:
434
mISDN_unregister_device(&card->isac.dch.dev);
435
error:
436
release_region(card->cfg, 256);
437
error_setup:
438
card->isac.release(&card->isac);
439
card->isar.release(&card->isar);
440
release_firmware(firmware);
441
error_fw:
442
pci_disable_device(card->pdev);
443
write_lock_irqsave(&card_lock, flags);
444
list_del(&card->list);
445
write_unlock_irqrestore(&card_lock, flags);
446
kfree(card);
447
return err;
448
}
449
450
static int __devinit
451
sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
452
{
453
int err = -ENOMEM;
454
struct sfax_hw *card = kzalloc(sizeof(struct sfax_hw), GFP_KERNEL);
455
456
if (!card) {
457
pr_info("No memory for Speedfax+ PCI\n");
458
return err;
459
}
460
card->pdev = pdev;
461
err = pci_enable_device(pdev);
462
if (err) {
463
kfree(card);
464
return err;
465
}
466
467
pr_notice("mISDN: Speedfax found adapter %s at %s\n",
468
(char *)ent->driver_data, pci_name(pdev));
469
470
card->cfg = pci_resource_start(pdev, 0);
471
card->irq = pdev->irq;
472
pci_set_drvdata(pdev, card);
473
err = setup_instance(card);
474
if (err)
475
pci_set_drvdata(pdev, NULL);
476
return err;
477
}
478
479
static void __devexit
480
sfax_remove_pci(struct pci_dev *pdev)
481
{
482
struct sfax_hw *card = pci_get_drvdata(pdev);
483
484
if (card)
485
release_card(card);
486
else
487
pr_debug("%s: drvdata already removed\n", __func__);
488
}
489
490
static struct pci_device_id sfaxpci_ids[] __devinitdata = {
491
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
492
PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
493
0, 0, (unsigned long) "Pyramid Speedfax + PCI"
494
},
495
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
496
PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
497
0, 0, (unsigned long) "Sedlbauer Speedfax + PCI"
498
},
499
{ }
500
};
501
MODULE_DEVICE_TABLE(pci, sfaxpci_ids);
502
503
static struct pci_driver sfaxpci_driver = {
504
.name = "speedfax+ pci",
505
.probe = sfaxpci_probe,
506
.remove = __devexit_p(sfax_remove_pci),
507
.id_table = sfaxpci_ids,
508
};
509
510
static int __init
511
Speedfax_init(void)
512
{
513
int err;
514
515
pr_notice("Sedlbauer Speedfax+ Driver Rev. %s\n",
516
SPEEDFAX_REV);
517
err = pci_register_driver(&sfaxpci_driver);
518
return err;
519
}
520
521
static void __exit
522
Speedfax_cleanup(void)
523
{
524
pci_unregister_driver(&sfaxpci_driver);
525
}
526
527
module_init(Speedfax_init);
528
module_exit(Speedfax_cleanup);
529
530