Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/applicom.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Derived from Applicom driver ac.c for SCO Unix */
3
/* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */
4
/* [email protected] 30/8/98 */
5
/* $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $ */
6
/* This module is for Linux 2.1 and 2.2 series kernels. */
7
/*****************************************************************************/
8
/* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt */
9
/* ceci pour reseter correctement apres une sortie sauvage */
10
/* J PAGET 02/05/94 passage V2.4.3 dans le traitement de d'interruption, */
11
/* LoopCount n'etait pas initialise a 0. */
12
/* F LAFORSE 04/07/95 version V2.6.0 lecture bidon apres acces a une carte */
13
/* pour liberer le bus */
14
/* J.PAGET 19/11/95 version V2.6.1 Nombre, addresse,irq n'est plus configure */
15
/* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */
16
/* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */
17
/* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */
18
/* addresses de base des cartes, IOCTL 6 plus complet */
19
/* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */
20
/* de code autre que le texte V2.6.1 en V2.8.0 */
21
/*****************************************************************************/
22
23
24
#include <linux/kernel.h>
25
#include <linux/module.h>
26
#include <linux/interrupt.h>
27
#include <linux/sched/signal.h>
28
#include <linux/slab.h>
29
#include <linux/errno.h>
30
#include <linux/mutex.h>
31
#include <linux/miscdevice.h>
32
#include <linux/pci.h>
33
#include <linux/wait.h>
34
#include <linux/init.h>
35
#include <linux/fs.h>
36
#include <linux/nospec.h>
37
38
#include <asm/io.h>
39
#include <linux/uaccess.h>
40
41
#include "applicom.h"
42
43
44
/* NOTE: We use for loops with {write,read}b() instead of
45
memcpy_{from,to}io throughout this driver. This is because
46
the board doesn't correctly handle word accesses - only
47
bytes.
48
*/
49
50
51
#undef DEBUG
52
53
#define MAX_BOARD 8 /* maximum of pc board possible */
54
#define MAX_ISA_BOARD 4
55
#define LEN_RAM_IO 0x800
56
57
#ifndef PCI_VENDOR_ID_APPLICOM
58
#define PCI_VENDOR_ID_APPLICOM 0x1389
59
#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
60
#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
61
#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
62
#endif
63
64
static DEFINE_MUTEX(ac_mutex);
65
static char *applicom_pci_devnames[] = {
66
"PCI board",
67
"PCI2000IBS / PCI2000CAN",
68
"PCI2000PFB"
69
};
70
71
static const struct pci_device_id applicom_pci_tbl[] = {
72
{ PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCIGENERIC) },
73
{ PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN) },
74
{ PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000PFB) },
75
{ 0 }
76
};
77
MODULE_DEVICE_TABLE(pci, applicom_pci_tbl);
78
79
MODULE_AUTHOR("David Woodhouse & Applicom International");
80
MODULE_DESCRIPTION("Driver for Applicom Profibus card");
81
MODULE_LICENSE("GPL");
82
MODULE_ALIAS_MISCDEV(AC_MINOR);
83
84
static struct applicom_board {
85
unsigned long PhysIO;
86
void __iomem *RamIO;
87
wait_queue_head_t FlagSleepSend;
88
long irq;
89
spinlock_t mutex;
90
} apbs[MAX_BOARD];
91
92
static unsigned int irq; /* interrupt number IRQ */
93
static unsigned long mem; /* physical segment of board */
94
95
module_param_hw(irq, uint, irq, 0);
96
MODULE_PARM_DESC(irq, "IRQ of the Applicom board");
97
module_param_hw(mem, ulong, iomem, 0);
98
MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board");
99
100
static unsigned int numboards; /* number of installed boards */
101
static volatile unsigned char Dummy;
102
static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec);
103
static unsigned int WriteErrorCount; /* number of write error */
104
static unsigned int ReadErrorCount; /* number of read error */
105
static unsigned int DeviceErrorCount; /* number of device error */
106
107
static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *);
108
static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *);
109
static long ac_ioctl(struct file *, unsigned int, unsigned long);
110
static irqreturn_t ac_interrupt(int, void *);
111
112
static const struct file_operations ac_fops = {
113
.owner = THIS_MODULE,
114
.read = ac_read,
115
.write = ac_write,
116
.unlocked_ioctl = ac_ioctl,
117
};
118
119
static struct miscdevice ac_miscdev = {
120
AC_MINOR,
121
"ac",
122
&ac_fops
123
};
124
125
static int dummy; /* dev_id for request_irq() */
126
127
static int ac_register_board(unsigned long physloc, void __iomem *loc,
128
unsigned char boardno)
129
{
130
volatile unsigned char byte_reset_it;
131
132
if((readb(loc + CONF_END_TEST) != 0x00) ||
133
(readb(loc + CONF_END_TEST + 1) != 0x55) ||
134
(readb(loc + CONF_END_TEST + 2) != 0xAA) ||
135
(readb(loc + CONF_END_TEST + 3) != 0xFF))
136
return 0;
137
138
if (!boardno)
139
boardno = readb(loc + NUMCARD_OWNER_TO_PC);
140
141
if (!boardno || boardno > MAX_BOARD) {
142
printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",
143
boardno, physloc, MAX_BOARD);
144
return 0;
145
}
146
147
if (apbs[boardno - 1].RamIO) {
148
printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n",
149
boardno, physloc, boardno, apbs[boardno-1].PhysIO);
150
return 0;
151
}
152
153
boardno--;
154
155
apbs[boardno].PhysIO = physloc;
156
apbs[boardno].RamIO = loc;
157
init_waitqueue_head(&apbs[boardno].FlagSleepSend);
158
spin_lock_init(&apbs[boardno].mutex);
159
byte_reset_it = readb(loc + RAM_IT_TO_PC);
160
161
numboards++;
162
return boardno + 1;
163
}
164
165
static void __exit applicom_exit(void)
166
{
167
unsigned int i;
168
169
misc_deregister(&ac_miscdev);
170
171
for (i = 0; i < MAX_BOARD; i++) {
172
173
if (!apbs[i].RamIO)
174
continue;
175
176
if (apbs[i].irq)
177
free_irq(apbs[i].irq, &dummy);
178
179
iounmap(apbs[i].RamIO);
180
}
181
}
182
183
static int __init applicom_init(void)
184
{
185
int i, numisa = 0;
186
struct pci_dev *dev = NULL;
187
void __iomem *RamIO;
188
int boardno, ret;
189
190
printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
191
192
/* No mem and irq given - check for a PCI card */
193
194
while ( (dev = pci_get_class(PCI_CLASS_OTHERS << 16, dev))) {
195
196
if (!pci_match_id(applicom_pci_tbl, dev))
197
continue;
198
199
if (pci_enable_device(dev)) {
200
pci_dev_put(dev);
201
return -EIO;
202
}
203
204
RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO);
205
206
if (!RamIO) {
207
printk(KERN_INFO "ac.o: Failed to ioremap PCI memory "
208
"space at 0x%llx\n",
209
(unsigned long long)pci_resource_start(dev, 0));
210
pci_disable_device(dev);
211
pci_dev_put(dev);
212
return -EIO;
213
}
214
215
printk(KERN_INFO "Applicom %s found at mem 0x%llx, irq %d\n",
216
applicom_pci_devnames[dev->device-1],
217
(unsigned long long)pci_resource_start(dev, 0),
218
dev->irq);
219
220
boardno = ac_register_board(pci_resource_start(dev, 0),
221
RamIO, 0);
222
if (!boardno) {
223
printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
224
iounmap(RamIO);
225
pci_disable_device(dev);
226
continue;
227
}
228
229
if (request_irq(dev->irq, &ac_interrupt, IRQF_SHARED, "Applicom PCI", &dummy)) {
230
printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
231
iounmap(RamIO);
232
pci_disable_device(dev);
233
apbs[boardno - 1].RamIO = NULL;
234
continue;
235
}
236
237
/* Enable interrupts. */
238
239
writeb(0x40, apbs[boardno - 1].RamIO + RAM_IT_FROM_PC);
240
241
apbs[boardno - 1].irq = dev->irq;
242
}
243
244
/* Finished with PCI cards. If none registered,
245
* and there was no mem/irq specified, exit */
246
247
if (!mem || !irq) {
248
if (numboards)
249
goto fin;
250
else {
251
printk(KERN_INFO "ac.o: No PCI boards found.\n");
252
printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n");
253
return -ENXIO;
254
}
255
}
256
257
/* Now try the specified ISA cards */
258
259
for (i = 0; i < MAX_ISA_BOARD; i++) {
260
RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
261
262
if (!RamIO) {
263
printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1);
264
continue;
265
}
266
267
if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
268
RamIO,i+1))) {
269
iounmap(RamIO);
270
continue;
271
}
272
273
printk(KERN_NOTICE "Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq);
274
275
if (!numisa) {
276
if (request_irq(irq, &ac_interrupt, IRQF_SHARED, "Applicom ISA", &dummy)) {
277
printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq);
278
iounmap(RamIO);
279
apbs[boardno - 1].RamIO = NULL;
280
}
281
else
282
apbs[boardno - 1].irq = irq;
283
}
284
else
285
apbs[boardno - 1].irq = 0;
286
287
numisa++;
288
}
289
290
if (!numisa)
291
printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found "
292
"at mem 0x%lx\n", mem);
293
294
fin:
295
init_waitqueue_head(&FlagSleepRec);
296
297
WriteErrorCount = 0;
298
ReadErrorCount = 0;
299
DeviceErrorCount = 0;
300
301
if (numboards) {
302
ret = misc_register(&ac_miscdev);
303
if (ret) {
304
printk(KERN_WARNING "ac.o: Unable to register misc device\n");
305
goto out;
306
}
307
for (i = 0; i < MAX_BOARD; i++) {
308
int serial;
309
char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
310
311
if (!apbs[i].RamIO)
312
continue;
313
314
for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
315
boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
316
317
boardname[serial] = 0;
318
319
320
printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d",
321
i+1, boardname,
322
(int)(readb(apbs[i].RamIO + VERS) >> 4),
323
(int)(readb(apbs[i].RamIO + VERS) & 0xF));
324
325
serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) +
326
(readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) +
327
(readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
328
329
if (serial != 0)
330
printk(" S/N %d\n", serial);
331
else
332
printk("\n");
333
}
334
return 0;
335
}
336
337
else
338
return -ENXIO;
339
340
out:
341
for (i = 0; i < MAX_BOARD; i++) {
342
if (!apbs[i].RamIO)
343
continue;
344
if (apbs[i].irq)
345
free_irq(apbs[i].irq, &dummy);
346
iounmap(apbs[i].RamIO);
347
}
348
return ret;
349
}
350
351
module_init(applicom_init);
352
module_exit(applicom_exit);
353
354
355
static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
356
{
357
unsigned int NumCard; /* Board number 1 -> 8 */
358
unsigned int IndexCard; /* Index board number 0 -> 7 */
359
unsigned char TicCard; /* Board TIC to send */
360
unsigned long flags; /* Current priority */
361
struct st_ram_io st_loc;
362
struct mailbox tmpmailbox;
363
#ifdef DEBUG
364
int c;
365
#endif
366
DECLARE_WAITQUEUE(wait, current);
367
368
if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
369
static int warncount = 5;
370
if (warncount) {
371
printk(KERN_INFO "Hmmm. write() of Applicom card, length %zd != expected %zd\n",
372
count, sizeof(struct st_ram_io) + sizeof(struct mailbox));
373
warncount--;
374
}
375
return -EINVAL;
376
}
377
378
if(copy_from_user(&st_loc, buf, sizeof(struct st_ram_io)))
379
return -EFAULT;
380
381
if(copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)],
382
sizeof(struct mailbox)))
383
return -EFAULT;
384
385
NumCard = st_loc.num_card; /* board number to send */
386
TicCard = st_loc.tic_des_from_pc; /* tic number to send */
387
IndexCard = NumCard - 1;
388
389
if (IndexCard >= MAX_BOARD)
390
return -EINVAL;
391
IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
392
393
if (!apbs[IndexCard].RamIO)
394
return -EINVAL;
395
396
#ifdef DEBUG
397
printk("Write to applicom card #%d. struct st_ram_io follows:",
398
IndexCard+1);
399
400
for (c = 0; c < sizeof(struct st_ram_io);) {
401
402
printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]);
403
404
for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {
405
printk(" %2.2X", ((unsigned char *) &st_loc)[c]);
406
}
407
}
408
409
printk("\nstruct mailbox follows:");
410
411
for (c = 0; c < sizeof(struct mailbox);) {
412
printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]);
413
414
for (c++; c % 8 && c < sizeof(struct mailbox); c++) {
415
printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]);
416
}
417
}
418
419
printk("\n");
420
#endif
421
422
spin_lock_irqsave(&apbs[IndexCard].mutex, flags);
423
424
/* Test octet ready correct */
425
if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) {
426
Dummy = readb(apbs[IndexCard].RamIO + VERS);
427
spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
428
printk(KERN_WARNING "APPLICOM driver write error board %d, DataFromPcReady = %d\n",
429
IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY));
430
DeviceErrorCount++;
431
return -EIO;
432
}
433
434
/* Place ourselves on the wait queue */
435
set_current_state(TASK_INTERRUPTIBLE);
436
add_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait);
437
438
/* Check whether the card is ready for us */
439
while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) {
440
Dummy = readb(apbs[IndexCard].RamIO + VERS);
441
/* It's busy. Sleep. */
442
443
spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
444
schedule();
445
if (signal_pending(current)) {
446
remove_wait_queue(&apbs[IndexCard].FlagSleepSend,
447
&wait);
448
return -EINTR;
449
}
450
spin_lock_irqsave(&apbs[IndexCard].mutex, flags);
451
set_current_state(TASK_INTERRUPTIBLE);
452
}
453
454
/* We may not have actually slept */
455
set_current_state(TASK_RUNNING);
456
remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait);
457
458
writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
459
460
/* Which is best - lock down the pages with rawio and then
461
copy directly, or use bounce buffers? For now we do the latter
462
because it works with 2.2 still */
463
{
464
unsigned char *from = (unsigned char *) &tmpmailbox;
465
void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC;
466
int c;
467
468
for (c = 0; c < sizeof(struct mailbox); c++)
469
writeb(*(from++), to++);
470
}
471
472
writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC);
473
writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC);
474
writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC);
475
writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
476
writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
477
writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
478
Dummy = readb(apbs[IndexCard].RamIO + VERS);
479
spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
480
return 0;
481
}
482
483
static int do_ac_read(int IndexCard, char __user *buf,
484
struct st_ram_io *st_loc, struct mailbox *mailbox)
485
{
486
void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
487
unsigned char *to = (unsigned char *)mailbox;
488
#ifdef DEBUG
489
int c;
490
#endif
491
492
st_loc->tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
493
st_loc->numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
494
495
496
{
497
int c;
498
499
for (c = 0; c < sizeof(struct mailbox); c++)
500
*(to++) = readb(from++);
501
}
502
writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
503
writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC);
504
writeb(IndexCard+1, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
505
writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC),
506
apbs[IndexCard].RamIO + TIC_ACK_FROM_PC);
507
writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
508
writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY);
509
writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
510
Dummy = readb(apbs[IndexCard].RamIO + VERS);
511
512
#ifdef DEBUG
513
printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard);
514
515
for (c = 0; c < sizeof(struct st_ram_io);) {
516
printk("\n%5.5X: %2.2X", c, ((unsigned char *)st_loc)[c]);
517
518
for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {
519
printk(" %2.2X", ((unsigned char *)st_loc)[c]);
520
}
521
}
522
523
printk("\nstruct mailbox follows:");
524
525
for (c = 0; c < sizeof(struct mailbox);) {
526
printk("\n%5.5X: %2.2X", c, ((unsigned char *)mailbox)[c]);
527
528
for (c++; c % 8 && c < sizeof(struct mailbox); c++) {
529
printk(" %2.2X", ((unsigned char *)mailbox)[c]);
530
}
531
}
532
printk("\n");
533
#endif
534
return (sizeof(struct st_ram_io) + sizeof(struct mailbox));
535
}
536
537
static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_t *ptr)
538
{
539
unsigned long flags;
540
unsigned int i;
541
unsigned char tmp;
542
int ret = 0;
543
DECLARE_WAITQUEUE(wait, current);
544
#ifdef DEBUG
545
int loopcount=0;
546
#endif
547
/* No need to ratelimit this. Only root can trigger it anyway */
548
if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
549
printk( KERN_WARNING "Hmmm. read() of Applicom card, length %zd != expected %zd\n",
550
count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
551
return -EINVAL;
552
}
553
554
while(1) {
555
/* Stick ourself on the wait queue */
556
set_current_state(TASK_INTERRUPTIBLE);
557
add_wait_queue(&FlagSleepRec, &wait);
558
559
/* Scan each board, looking for one which has a packet for us */
560
for (i=0; i < MAX_BOARD; i++) {
561
if (!apbs[i].RamIO)
562
continue;
563
spin_lock_irqsave(&apbs[i].mutex, flags);
564
565
tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);
566
567
if (tmp == 2) {
568
struct st_ram_io st_loc;
569
struct mailbox mailbox;
570
571
/* Got a packet for us */
572
memset(&st_loc, 0, sizeof(st_loc));
573
ret = do_ac_read(i, buf, &st_loc, &mailbox);
574
spin_unlock_irqrestore(&apbs[i].mutex, flags);
575
set_current_state(TASK_RUNNING);
576
remove_wait_queue(&FlagSleepRec, &wait);
577
578
if (copy_to_user(buf, &st_loc, sizeof(st_loc)))
579
return -EFAULT;
580
if (copy_to_user(buf + sizeof(st_loc), &mailbox, sizeof(mailbox)))
581
return -EFAULT;
582
return tmp;
583
}
584
585
if (tmp > 2) {
586
/* Got an error */
587
Dummy = readb(apbs[i].RamIO + VERS);
588
589
spin_unlock_irqrestore(&apbs[i].mutex, flags);
590
set_current_state(TASK_RUNNING);
591
remove_wait_queue(&FlagSleepRec, &wait);
592
593
printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n",
594
i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
595
DeviceErrorCount++;
596
return -EIO;
597
}
598
599
/* Nothing for us. Try the next board */
600
Dummy = readb(apbs[i].RamIO + VERS);
601
spin_unlock_irqrestore(&apbs[i].mutex, flags);
602
603
} /* per board */
604
605
/* OK - No boards had data for us. Sleep now */
606
607
schedule();
608
remove_wait_queue(&FlagSleepRec, &wait);
609
610
if (signal_pending(current))
611
return -EINTR;
612
613
#ifdef DEBUG
614
if (loopcount++ > 2) {
615
printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
616
}
617
#endif
618
}
619
}
620
621
static irqreturn_t ac_interrupt(int vec, void *dev_instance)
622
{
623
unsigned int i;
624
unsigned int FlagInt;
625
unsigned int LoopCount;
626
int handled = 0;
627
628
// printk("Applicom interrupt on IRQ %d occurred\n", vec);
629
630
LoopCount = 0;
631
632
do {
633
FlagInt = 0;
634
for (i = 0; i < MAX_BOARD; i++) {
635
636
/* Skip if this board doesn't exist */
637
if (!apbs[i].RamIO)
638
continue;
639
640
spin_lock(&apbs[i].mutex);
641
642
/* Skip if this board doesn't want attention */
643
if(readb(apbs[i].RamIO + RAM_IT_TO_PC) == 0) {
644
spin_unlock(&apbs[i].mutex);
645
continue;
646
}
647
648
handled = 1;
649
FlagInt = 1;
650
writeb(0, apbs[i].RamIO + RAM_IT_TO_PC);
651
652
if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) {
653
printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n",
654
i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
655
DeviceErrorCount++;
656
}
657
658
if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) &&
659
(readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) {
660
661
printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n",
662
i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY));
663
DeviceErrorCount++;
664
}
665
666
if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { /* mailbox sent by the card ? */
667
if (waitqueue_active(&FlagSleepRec)) {
668
wake_up_interruptible(&FlagSleepRec);
669
}
670
}
671
672
if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) { /* ram i/o free for write by pc ? */
673
if (waitqueue_active(&apbs[i].FlagSleepSend)) { /* process sleep during read ? */
674
wake_up_interruptible(&apbs[i].FlagSleepSend);
675
}
676
}
677
Dummy = readb(apbs[i].RamIO + VERS);
678
679
if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) {
680
/* There's another int waiting on this card */
681
spin_unlock(&apbs[i].mutex);
682
i--;
683
} else {
684
spin_unlock(&apbs[i].mutex);
685
}
686
}
687
if (FlagInt)
688
LoopCount = 0;
689
else
690
LoopCount++;
691
} while(LoopCount < 2);
692
return IRQ_RETVAL(handled);
693
}
694
695
696
697
static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
698
699
{ /* @ ADG ou ATO selon le cas */
700
int i;
701
unsigned char IndexCard;
702
void __iomem *pmem;
703
int ret = 0;
704
static int warncount = 10;
705
volatile unsigned char byte_reset_it;
706
struct st_ram_io *adgl;
707
void __user *argp = (void __user *)arg;
708
709
/* In general, the device is only openable by root anyway, so we're not
710
particularly concerned that bogus ioctls can flood the console. */
711
712
adgl = memdup_user(argp, sizeof(struct st_ram_io));
713
if (IS_ERR(adgl))
714
return PTR_ERR(adgl);
715
716
mutex_lock(&ac_mutex);
717
IndexCard = adgl->num_card-1;
718
719
if (cmd != 6 && IndexCard >= MAX_BOARD)
720
goto err;
721
IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
722
723
if (cmd != 6 && !apbs[IndexCard].RamIO)
724
goto err;
725
726
switch (cmd) {
727
728
case 0:
729
pmem = apbs[IndexCard].RamIO;
730
for (i = 0; i < sizeof(struct st_ram_io); i++)
731
((unsigned char *)adgl)[i]=readb(pmem++);
732
if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
733
ret = -EFAULT;
734
break;
735
case 1:
736
pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
737
for (i = 0; i < 4; i++)
738
adgl->conf_end_test[i] = readb(pmem++);
739
for (i = 0; i < 2; i++)
740
adgl->error_code[i] = readb(pmem++);
741
for (i = 0; i < 4; i++)
742
adgl->parameter_error[i] = readb(pmem++);
743
pmem = apbs[IndexCard].RamIO + VERS;
744
adgl->vers = readb(pmem);
745
pmem = apbs[IndexCard].RamIO + TYPE_CARD;
746
for (i = 0; i < 20; i++)
747
adgl->reserv1[i] = readb(pmem++);
748
*(int *)&adgl->reserv1[20] =
749
(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) +
750
(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) +
751
(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );
752
753
if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
754
ret = -EFAULT;
755
break;
756
case 2:
757
pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
758
for (i = 0; i < 10; i++)
759
writeb(0xff, pmem++);
760
writeb(adgl->data_from_pc_ready,
761
apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
762
763
writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
764
765
for (i = 0; i < MAX_BOARD; i++) {
766
if (apbs[i].RamIO) {
767
byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC);
768
}
769
}
770
break;
771
case 3:
772
pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;
773
writeb(adgl->tic_des_from_pc, pmem);
774
break;
775
case 4:
776
pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
777
adgl->tic_owner_to_pc = readb(pmem++);
778
adgl->numcard_owner_to_pc = readb(pmem);
779
if (copy_to_user(argp, adgl,sizeof(struct st_ram_io)))
780
ret = -EFAULT;
781
break;
782
case 5:
783
writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
784
writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
785
writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
786
writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
787
writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
788
break;
789
case 6:
790
printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n");
791
printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards);
792
printk(KERN_INFO "Segment of board ........... %X\n", (int) mem);
793
printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq);
794
for (i = 0; i < MAX_BOARD; i++) {
795
int serial;
796
char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
797
798
if (!apbs[i].RamIO)
799
continue;
800
801
for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
802
boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
803
boardname[serial] = 0;
804
805
printk(KERN_INFO "Prom version board %d ....... V%d.%d %s",
806
i+1,
807
(int)(readb(apbs[i].RamIO + VERS) >> 4),
808
(int)(readb(apbs[i].RamIO + VERS) & 0xF),
809
boardname);
810
811
812
serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) +
813
(readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) +
814
(readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
815
816
if (serial != 0)
817
printk(" S/N %d\n", serial);
818
else
819
printk("\n");
820
}
821
if (DeviceErrorCount != 0)
822
printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount);
823
if (ReadErrorCount != 0)
824
printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount);
825
if (WriteErrorCount != 0)
826
printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount);
827
if (waitqueue_active(&FlagSleepRec))
828
printk(KERN_INFO "Process in read pending\n");
829
for (i = 0; i < MAX_BOARD; i++) {
830
if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend))
831
printk(KERN_INFO "Process in write pending board %d\n",i+1);
832
}
833
break;
834
default:
835
ret = -ENOTTY;
836
break;
837
}
838
Dummy = readb(apbs[IndexCard].RamIO + VERS);
839
kfree(adgl);
840
mutex_unlock(&ac_mutex);
841
return ret;
842
843
err:
844
if (warncount) {
845
pr_warn("APPLICOM driver IOCTL, bad board number %d\n",
846
(int)IndexCard + 1);
847
warncount--;
848
}
849
kfree(adgl);
850
mutex_unlock(&ac_mutex);
851
return -EINVAL;
852
853
}
854
855
856