* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / applicom.c
blobc311e58cda480aea425eeb009f164c296e8da66d
1 /* Derived from Applicom driver ac.c for SCO Unix */
2 /* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */
3 /* Dave@mvhi.com 30/8/98 */
4 /* $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $ */
5 /* This module is for Linux 2.1 and 2.2 series kernels. */
6 /*****************************************************************************/
7 /* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt */
8 /* ceci pour reseter correctement apres une sortie sauvage */
9 /* J PAGET 02/05/94 passage V2.4.3 dans le traitement de d'interruption, */
10 /* LoopCount n'etait pas initialise a 0. */
11 /* F LAFORSE 04/07/95 version V2.6.0 lecture bidon apres acces a une carte */
12 /* pour liberer le bus */
13 /* J.PAGET 19/11/95 version V2.6.1 Nombre, addresse,irq n'est plus configure */
14 /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter */
15 /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3 */
16 /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes */
17 /* adresses de base des cartes, IOCTL 6 plus complet */
18 /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification */
19 /* de code autre que le texte V2.6.1 en V2.8.0 */
20 /*****************************************************************************/
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <asm/errno.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <linux/miscdevice.h>
29 #include <linux/pci.h>
30 #include <linux/wait.h>
31 #include <linux/init.h>
32 #include "applicom.h"
33 #ifndef LINUX_VERSION_CODE
34 #include <linux/version.h>
35 #endif
37 #undef DEBUG
38 #define DEVPRIO PZERO+8
39 #define FALSE 0
40 #define TRUE ~FALSE
41 #define MAX_BOARD 8 /* maximum of pc board possible */
42 #define MAX_ISA_BOARD 4
43 #define LEN_RAM_IO 0x800
44 #define AC_MINOR 157
46 #ifndef PCI_VENDOR_ID_APPLICOM
47 #define PCI_VENDOR_ID_APPLICOM 0x1389
48 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
49 #define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
50 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
51 #define MAX_PCI_DEVICE_NUM 3
52 #endif
54 static char *applicom_pci_devnames[]={
55 "PCI board", "PCI2000IBS / PCI2000CAN", "PCI2000PFB"};
57 MODULE_AUTHOR("David Woodhouse & Applicom International");
58 MODULE_DESCRIPTION("Driver for Applicom Profibus card");
59 MODULE_PARM(irq, "i");
60 MODULE_PARM_DESC(irq, "IRQ of the Applicom board");
61 MODULE_PARM(mem,"i");
62 MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board");
64 MODULE_SUPPORTED_DEVICE("ac");
67 struct applicom_board {
68 unsigned long PhysIO;
69 unsigned long RamIO;
70 #if LINUX_VERSION_CODE > 0x20300
71 wait_queue_head_t FlagSleepSend;
72 #else
73 struct wait_queue *FlagSleepSend;
74 #endif
75 long irq;
76 } apbs[MAX_BOARD];
78 static unsigned int irq=0; /* interrupt number IRQ */
79 static unsigned long mem=0; /* physical segment of board */
81 static unsigned int numboards; /* number of installed boards */
82 static volatile unsigned char Dummy;
83 #if LINUX_VERSION_CODE > 0x20300
84 static DECLARE_WAIT_QUEUE_HEAD (FlagSleepRec);
85 #else
86 static struct wait_queue *FlagSleepRec;
87 #endif
88 static unsigned int WriteErrorCount; /* number of write error */
89 static unsigned int ReadErrorCount; /* number of read error */
90 static unsigned int DeviceErrorCount; /* number of device error */
92 static loff_t ac_llseek(struct file *file, loff_t offset, int origin);
93 static int ac_open(struct inode *inode, struct file *filp);
94 static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr);
95 static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos);
96 static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
97 static int ac_release(struct inode *inode, struct file *file);
98 static void ac_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
100 struct file_operations ac_fops={
101 ac_llseek, /* llseek */
102 ac_read, /* read */
103 ac_write, /* write */
104 NULL, /* readdir */
105 NULL, /* poll */
106 ac_ioctl, /* ioctl */
107 NULL, /* mmap */
108 ac_open, /* open */
109 NULL, /* flush */
110 ac_release, /* release */
111 NULL /* fsync */
114 struct miscdevice ac_miscdev={
115 AC_MINOR,
116 "ac",
117 &ac_fops
120 int ac_register_board(unsigned long physloc, unsigned long loc,
121 unsigned char boardno)
123 volatile unsigned char byte_reset_it;
125 if((readb(loc + CONF_END_TEST) != 0x00) ||
126 (readb(loc + CONF_END_TEST + 1) != 0x55) ||
127 (readb(loc + CONF_END_TEST + 2) != 0xAA) ||
128 (readb(loc + CONF_END_TEST + 3) != 0xFF))
129 return 0;
132 if (!boardno)
133 boardno = readb(loc + NUMCARD_OWNER_TO_PC);
135 if (!boardno && boardno > MAX_BOARD)
137 printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",boardno, physloc, MAX_BOARD);
138 return 0;
141 if (apbs[boardno-1].RamIO)
143 printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n",
144 boardno, physloc, boardno, apbs[boardno-1].PhysIO);
145 return 0;
148 boardno--;
150 apbs[boardno].PhysIO = physloc;
151 apbs[boardno].RamIO = loc;
152 #if LINUX_VERSION_CODE > 0x20300
153 init_waitqueue_head(&apbs[boardno].FlagSleepSend);
154 #else
155 apbs[boardno].FlagSleepSend = NULL;
156 #endif
157 byte_reset_it = readb(loc + RAM_IT_TO_PC);
159 numboards++;
160 return boardno+1;
163 #ifdef MODULE
165 #define applicom_init init_module
167 void cleanup_module(void)
169 int i;
171 misc_deregister(&ac_miscdev);
172 for (i=0; i< MAX_BOARD; i++)
174 if (!apbs[i].RamIO)
175 continue;
176 iounmap((void *)apbs[i].RamIO);
177 if (apbs[i].irq)
178 free_irq(apbs[i].irq,&ac_open);
180 // printk("Removing Applicom module\n");
183 #endif /* MODULE */
185 int __init applicom_init(void)
187 int i, numisa=0;
188 struct pci_dev *dev = NULL;
189 void *RamIO;
190 int boardno;
191 #if LINUX_VERSION_CODE > 0x20300
192 #define PCI_BASE_ADDRESS(dev) (dev->resource[0].start)
193 #else
194 #define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
195 #endif
197 printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $\n");
199 /* No mem and irq given - check for a PCI card */
201 while ( (dev = pci_find_device(PCI_VENDOR_ID_APPLICOM, 1, dev)))
203 // mem = dev->base_address[0];
204 // irq = dev->irq;
206 RamIO = ioremap(PCI_BASE_ADDRESS(dev), LEN_RAM_IO);
208 if (!RamIO) {
209 printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev));
210 return -EIO;
213 printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n",
214 applicom_pci_devnames[dev->device-1], PCI_BASE_ADDRESS(dev),
215 dev->irq);
217 if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev),
218 (unsigned long)RamIO,0)))
220 printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
221 iounmap(RamIO);
222 continue;
225 if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &ac_open))
227 printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
228 iounmap(RamIO);
229 apbs[boardno-1].RamIO = 0;
230 continue;
233 /* Enable interrupts. */
235 writeb(0x40, apbs[boardno-1].RamIO + RAM_IT_FROM_PC);
237 apbs[boardno-1].irq = dev->irq;
240 /* Finished with PCI cards. If none registered,
241 * and there was no mem/irq specified, exit */
243 if (!mem || !irq)
245 if (numboards)
246 goto fin;
247 else
249 printk(KERN_INFO "ac.o: No PCI boards found.\n");
250 printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n");
251 return -ENXIO;
255 /* Now try the specified ISA cards */
257 RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD);
259 if (!RamIO) {
260 printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n",mem);
263 for (i=0; i< MAX_ISA_BOARD; i++)
265 RamIO = ioremap(mem+ (LEN_RAM_IO*i), LEN_RAM_IO);
267 if (!RamIO) {
268 printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n",i+1);
269 continue;
272 if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
273 (unsigned long)RamIO,i+1))) {
274 iounmap(RamIO);
275 continue;
278 printk("Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq);
280 if (!numisa)
282 if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open))
284 printk("Could not allocate IRQ %d for ISA Applicom device.\n", irq);
285 iounmap((void *)RamIO);
286 apbs[boardno-1].RamIO = 0;
288 apbs[boardno-1].irq=irq;
290 else
291 apbs[boardno-1].irq=0;
293 numisa++;
296 if (!numisa)
297 printk("ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem);
299 #if LINUX_VERSION_CODE > 0x20300
300 init_waitqueue_head(&FlagSleepRec);
301 #else
302 FlagSleepRec = NULL;
303 #endif
304 WriteErrorCount = 0;
305 ReadErrorCount = 0;
306 DeviceErrorCount = 0;
308 fin:
309 if (numboards)
311 misc_register (&ac_miscdev);
312 for (i=0; i<MAX_BOARD; i++)
314 int serial;
315 char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
317 if (!apbs[i].RamIO)
318 continue;
320 for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
321 boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
322 boardname[serial]=0;
325 printk("Applicom board %d: %s, PROM V%d.%d",
326 i+1, boardname,
327 (int)(readb(apbs[i].RamIO + VERS) >> 4),
328 (int)(readb(apbs[i].RamIO + VERS) & 0xF));
330 serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) +
331 (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) +
332 (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
334 if (serial != 0)
335 printk (" S/N %d\n", serial);
336 else
337 printk("\n");
339 return 0;
342 else
343 return -ENXIO;
347 #ifndef MODULE
348 __initcall (applicom_init);
349 #endif
351 static loff_t ac_llseek(struct file *file, loff_t offset, int origin)
353 return -ESPIPE;
356 static int ac_open(struct inode *inode, struct file *filp)
358 MOD_INC_USE_COUNT;
359 return 0;
362 static int ac_release(struct inode *inode, struct file *file)
364 MOD_DEC_USE_COUNT;
365 return 0;
369 static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos)
371 unsigned int NumCard; /* Board number 1 -> 8 */
372 unsigned int IndexCard; /* Index board number 0 -> 7 */
373 unsigned char TicCard; /* Board TIC to send */
374 unsigned long flags; /* Current priority */
375 struct st_ram_io st_loc;
376 struct mailbox tmpmailbox;
378 if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
379 printk("Hmmm. write() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
380 return -EINVAL;
383 if(copy_from_user (&st_loc, buf, sizeof(struct st_ram_io))) {
384 return -EFAULT;
386 if(copy_from_user (&tmpmailbox, &buf[sizeof(struct st_ram_io)], sizeof(struct mailbox))) {
387 return -EFAULT;
390 NumCard = st_loc.num_card; /* board number to send */
391 TicCard = st_loc.tic_des_from_pc; /* tic number to send */
392 IndexCard = NumCard -1;
393 if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO)
394 { /* User board number not OK */
395 // printk("Write to invalid Applicom board %d\n", NumCard);
396 return -EINVAL; /* Return error code user buffer */
399 #ifdef DEBUG
401 int c;
403 printk("Write to applicom card #%d. struct st_ram_io follows:",NumCard);
407 for (c=0; c< sizeof(struct st_ram_io);)
409 printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]);
411 for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++)
413 printk(" %2.2X",((unsigned char *)&st_loc)[c]);
417 printk("\nstruct mailbox follows:");
419 for (c=0; c< sizeof(struct mailbox);)
421 printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]);
423 for (c++ ; c%8 && c<sizeof(struct mailbox); c++)
425 printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]);
429 printk("\n");
432 #endif
434 save_flags (flags);
435 cli(); /* disable interrupt */
437 if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) /* Test octet ready correct */
439 Dummy = readb(apbs[IndexCard].RamIO + VERS);
440 restore_flags(flags);
441 printk("APPLICOM driver write error board %d, DataFromPcReady = %d\n",
442 IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY));
443 DeviceErrorCount++;
444 return -EIO;
446 while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0)
448 Dummy = readb(apbs[IndexCard].RamIO + VERS);
449 restore_flags(flags);
450 interruptible_sleep_on (&apbs[IndexCard].FlagSleepSend);
451 if (signal_pending(current))
452 return -EINTR;
453 save_flags(flags);
454 cli();
456 writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
458 // memcpy_toio ((void *)apbs[IndexCard].PtrRamFromPc, (void *)&tmpmailbox, sizeof(struct mailbox));
460 unsigned char *from = (unsigned char *)&tmpmailbox;
461 unsigned long to = (unsigned long)apbs[IndexCard].RamIO + RAM_FROM_PC;
462 int c;
464 for (c=0; c<sizeof(struct mailbox) ; c++)
465 writeb(*(from++), to++);
467 writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC);
468 writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC);
469 writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC);
470 writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
471 writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
472 writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
473 Dummy = readb(apbs[IndexCard].RamIO + VERS);
474 restore_flags (flags);
475 return 0;
478 static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr)
480 unsigned int NumCard; /* board number 1 -> 8 */
481 unsigned int IndexCard; /* index board number 0 -> 7 */
482 unsigned long flags;
483 unsigned int i;
484 unsigned char tmp=0;
485 struct st_ram_io st_loc;
486 struct mailbox tmpmailbox; /* bounce buffer - can't copy to user space with cli() */
489 if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
490 printk("Hmmm. read() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
491 return -EINVAL;
494 save_flags(flags);
495 cli();
497 i = 0;
499 while (tmp != 2)
501 for (i=0; i < MAX_BOARD; i++)
503 if (!apbs[i].RamIO)
504 continue;
506 tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);
508 if (tmp == 2)
509 break;
511 if (tmp > 2) /* Test octet ready correct */
513 Dummy = readb(apbs[i].RamIO + VERS);
514 restore_flags(flags);
515 printk("APPLICOM driver read error board %d, DataToPcReady = %d\n",
516 i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
517 DeviceErrorCount++;
518 return -EIO;
520 Dummy = readb(apbs[i].RamIO + VERS);
523 if (tmp != 2)
525 restore_flags(flags);
526 interruptible_sleep_on (&FlagSleepRec);
527 if (signal_pending(current))
528 return -EINTR;
529 save_flags(flags);
530 cli();
534 IndexCard = i;
535 NumCard = i+1;
536 st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
537 st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
540 // memcpy_fromio(&tmpmailbox, apbs[IndexCard].PtrRamToPc, sizeof(struct mailbox));
542 unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
543 unsigned char *to = (unsigned char *)&tmpmailbox;
544 int c;
546 for (c=0; c<sizeof(struct mailbox) ; c++)
547 *(to++) = readb(from++);
549 writeb(1,apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
550 writeb(1,apbs[IndexCard].RamIO + TYP_ACK_FROM_PC);
551 writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
552 writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC),
553 apbs[IndexCard].RamIO + TIC_ACK_FROM_PC);
554 writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
555 writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY);
556 writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
557 Dummy = readb(apbs[IndexCard].RamIO + VERS);
558 restore_flags(flags);
560 #ifdef DEBUG
561 { int c;
563 printk("Read from applicom card #%d. struct st_ram_io follows:",NumCard);
565 for (c=0; c< sizeof(struct st_ram_io);)
567 printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]);
569 for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++)
571 printk(" %2.2X",((unsigned char *)&st_loc)[c]);
575 printk("\nstruct mailbox follows:");
577 for (c=0; c< sizeof(struct mailbox);)
579 printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]);
581 for (c++ ; c%8 && c<sizeof(struct mailbox); c++)
583 printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]);
586 printk("\n");
589 #endif
592 /* Je suis stupide. DW. */
594 if(copy_to_user (buf, &st_loc, sizeof(struct st_ram_io)))
595 return -EFAULT;
596 if(copy_to_user (&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox)))
597 return -EFAULT;
599 return 0;
602 static void ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs)
604 unsigned int i;
605 unsigned int FlagInt;
606 unsigned int LoopCount;
607 // volatile unsigned char ResetIntBoard;
609 // printk("Applicom interrupt on IRQ %d occurred\n", vec);
611 LoopCount = 0;
612 // for(i=boardno;i<MAX_BOARD;i++) /* loop for not configured board */
613 // if (apbs[i].RamIO)
614 // ResetIntBoard = *apbs[i].PtrRamItToPc; /* reset interrupt of unused boards */
618 FlagInt = FALSE;
619 for(i=0;i<MAX_BOARD;i++)
621 if (!apbs[i].RamIO)
622 continue;
624 if(readb(apbs[i].RamIO + RAM_IT_TO_PC) != 0)
625 FlagInt = TRUE;
626 writeb(0, apbs[i].RamIO + RAM_IT_TO_PC);
628 if(readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2)
630 printk("APPLICOM driver interrupt err board %d, DataToPcReady = %d\n",
631 i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
632 DeviceErrorCount++;
634 if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) &&
635 (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6))
637 printk("APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n",
638 i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY));
639 DeviceErrorCount++;
641 if(readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) /* mailbox sent by the card ? */
643 wake_up_interruptible(&FlagSleepRec);
645 if(readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) /* ram i/o free for write by pc ? */
647 if(waitqueue_active(&apbs[i].FlagSleepSend)) /* process sleep during read ? */
649 wake_up_interruptible(&apbs[i].FlagSleepSend);
652 Dummy = readb(apbs[i].RamIO + VERS);
654 if(readb(apbs[i].RamIO + RAM_IT_TO_PC))
655 i--; /* There's another int waiting on this card */
657 if(FlagInt) LoopCount = 0;
658 else LoopCount++;
660 while(LoopCount < 2);
664 static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
666 { /* @ ADG ou ATO selon le cas */
667 int i;
668 unsigned char IndexCard;
669 unsigned long pmem ;
670 volatile unsigned char byte_reset_it;
671 struct st_ram_io adgl ;
672 unsigned char TmpRamIo[sizeof(struct st_ram_io)];
675 if (copy_from_user (&adgl, (void *)arg,sizeof(struct st_ram_io)))
676 return -EFAULT;
678 IndexCard = adgl.num_card-1;
679 if(cmd != 0 && cmd != 6 &&
680 ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO))
682 printk("APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
683 printk("apbs[%d].RamIO = %lx\n",IndexCard, apbs[IndexCard].RamIO);
684 return -EINVAL;
687 switch( cmd )
689 case 0 :
690 pmem = apbs[IndexCard].RamIO;
691 for(i=0;i<sizeof(struct st_ram_io);i++)TmpRamIo[i]=readb(pmem++);
692 if (copy_to_user((void *)arg, TmpRamIo, sizeof(struct st_ram_io)))
693 return -EFAULT;
694 break;
695 case 1 :
696 pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
697 for (i=0;i<4;i++)
698 adgl.conf_end_test[i] = readb(pmem++);
699 for (i=0;i<2;i++)
700 adgl.error_code[i] = readb(pmem++);
701 for (i=0;i<4;i++)
702 adgl.parameter_error[i] = readb(pmem++);
703 pmem = apbs[IndexCard].RamIO + VERS;
704 adgl.vers = readb(pmem);
705 pmem = apbs[IndexCard].RamIO + TYPE_CARD;
706 for (i=0;i<20;i++)
707 adgl.reserv1[i] = readb(pmem++);
708 *(int *)&adgl.reserv1[20] =
709 (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) +
710 (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) +
711 (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );
713 if (copy_to_user ((void *)arg, &adgl, sizeof(struct st_ram_io)))
714 return -EFAULT;
715 break;
716 case 2 :
717 pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
718 for (i=0;i<10;i++)
719 writeb(0xff, pmem++);
720 writeb(adgl.data_from_pc_ready,
721 apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
723 writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
724 #if LINUX_VERSION_CODE > 0x20300
725 init_waitqueue_head (&FlagSleepRec);
726 #else
727 FlagSleepRec = NULL;
728 #endif
729 for (i=0;i<MAX_BOARD;i++)
731 if (apbs[i].RamIO)
733 #if LINUX_VERSION_CODE > 0x20300
734 init_waitqueue_head (&apbs[i].FlagSleepSend);
735 #else
736 apbs[i].FlagSleepSend = NULL;
737 #endif
738 byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC);
741 break ;
742 case 3 :
743 pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;
744 writeb(adgl.tic_des_from_pc, pmem);
745 break;
746 case 4 :
747 pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
748 adgl.tic_owner_to_pc = readb(pmem++);
749 adgl.numcard_owner_to_pc = readb(pmem);
750 if (copy_to_user ((void *)arg, &adgl,sizeof(struct st_ram_io)))
751 return -EFAULT;
752 break;
753 case 5 :
754 writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
755 writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
756 writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
757 writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
758 writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
759 break ;
760 case 6 :
761 printk("APPLICOM driver release .... V2.8.0\n");
762 printk("Number of installed boards . %d\n",(int)numboards);
763 printk("Segment of board ........... %X\n",(int)mem);
764 printk("Interrupt IRQ number ....... %d\n",(int)irq);
765 for(i=0;i<MAX_BOARD;i++)
767 int serial;
768 char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
770 if (!apbs[i].RamIO)
771 continue;
774 for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
775 boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
776 boardname[serial]=0;
779 printk("Prom version board %d ....... V%d.%d %s",
780 i+1,
781 (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4),
782 (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF),
783 boardname);
786 serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) +
787 (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) +
788 (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
790 if (serial != 0)
791 printk (" S/N %d\n", serial);
792 else
793 printk("\n");
795 if(DeviceErrorCount != 0)
796 printk("DeviceErrorCount ........... %d\n",DeviceErrorCount);
797 if(ReadErrorCount != 0)
798 printk("ReadErrorCount ............. %d\n",ReadErrorCount);
799 if(WriteErrorCount != 0)
800 printk("WriteErrorCount ............ %d\n",WriteErrorCount);
801 if(waitqueue_active(&FlagSleepRec))
802 printk("Process in read pending\n");
803 for(i=0;i<MAX_BOARD;i++)
805 if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend))
806 printk("Process in write pending board %d\n",i+1);
808 break;
809 default :
810 printk("APPLICOM driver ioctl, unknown function code %d\n",cmd) ;
811 return -EINVAL;
812 break;
814 Dummy = readb(apbs[IndexCard].RamIO + VERS);
815 return 0;
818 #ifndef MODULE
819 static int __init applicom_setup(char *str)
821 int ints[4];
823 (void)get_options(str, 4, ints);
825 if (ints[0] > 2) {
826 printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n");
829 if (ints[0] < 2) {
830 printk("applicom numargs: %d\n", ints[0]);
831 return 0;
834 mem=ints[1];
835 irq=ints[2];
836 return 1;
838 #if LINUX_VERSION_CODE > 0x20300
839 __setup("applicom=", applicom_setup);
840 #endif
841 #endif /* MODULE */