Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Derived from Applicom driver ac.c for SCO Unix                            */
0003 /* Ported by David Woodhouse, Axiom (Cambridge) Ltd.                         */
0004 /* dwmw2@infradead.org 30/8/98                                               */
0005 /* $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $              */
0006 /* This module is for Linux 2.1 and 2.2 series kernels.                      */
0007 /*****************************************************************************/
0008 /* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt  */
0009 /* ceci pour reseter correctement apres une sortie sauvage                   */
0010 /* J PAGET 02/05/94 passage V2.4.3 dans le traitement de d'interruption,     */
0011 /* LoopCount n'etait pas initialise a 0.                                     */
0012 /* F LAFORSE 04/07/95 version V2.6.0 lecture bidon apres acces a une carte   */
0013 /*           pour liberer le bus                                             */
0014 /* J.PAGET 19/11/95 version V2.6.1 Nombre, addresse,irq n'est plus configure */
0015 /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter  */
0016 /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3    */
0017 /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes       */
0018 /* addresses de base des cartes, IOCTL 6 plus complet                         */
0019 /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification  */
0020 /* de code autre que le texte V2.6.1 en V2.8.0                               */
0021 /*****************************************************************************/
0022 
0023 
0024 #include <linux/kernel.h>
0025 #include <linux/module.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/sched/signal.h>
0028 #include <linux/slab.h>
0029 #include <linux/errno.h>
0030 #include <linux/mutex.h>
0031 #include <linux/miscdevice.h>
0032 #include <linux/pci.h>
0033 #include <linux/wait.h>
0034 #include <linux/init.h>
0035 #include <linux/fs.h>
0036 #include <linux/nospec.h>
0037 
0038 #include <asm/io.h>
0039 #include <linux/uaccess.h>
0040 
0041 #include "applicom.h"
0042 
0043 
0044 /* NOTE: We use for loops with {write,read}b() instead of 
0045    memcpy_{from,to}io throughout this driver. This is because
0046    the board doesn't correctly handle word accesses - only
0047    bytes. 
0048 */
0049 
0050 
0051 #undef DEBUG
0052 
0053 #define MAX_BOARD 8     /* maximum of pc board possible */
0054 #define MAX_ISA_BOARD 4
0055 #define LEN_RAM_IO 0x800
0056 
0057 #ifndef PCI_VENDOR_ID_APPLICOM
0058 #define PCI_VENDOR_ID_APPLICOM                0x1389
0059 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC     0x0001
0060 #define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
0061 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
0062 #endif
0063 
0064 static DEFINE_MUTEX(ac_mutex);
0065 static char *applicom_pci_devnames[] = {
0066     "PCI board",
0067     "PCI2000IBS / PCI2000CAN",
0068     "PCI2000PFB"
0069 };
0070 
0071 static const struct pci_device_id applicom_pci_tbl[] = {
0072     { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCIGENERIC) },
0073     { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN) },
0074     { PCI_VDEVICE(APPLICOM, PCI_DEVICE_ID_APPLICOM_PCI2000PFB) },
0075     { 0 }
0076 };
0077 MODULE_DEVICE_TABLE(pci, applicom_pci_tbl);
0078 
0079 MODULE_AUTHOR("David Woodhouse & Applicom International");
0080 MODULE_DESCRIPTION("Driver for Applicom Profibus card");
0081 MODULE_LICENSE("GPL");
0082 MODULE_ALIAS_MISCDEV(AC_MINOR);
0083 
0084 static struct applicom_board {
0085     unsigned long PhysIO;
0086     void __iomem *RamIO;
0087     wait_queue_head_t FlagSleepSend;
0088     long irq;
0089     spinlock_t mutex;
0090 } apbs[MAX_BOARD];
0091 
0092 static unsigned int irq;    /* interrupt number IRQ       */
0093 static unsigned long mem;   /* physical segment of board  */
0094 
0095 module_param_hw(irq, uint, irq, 0);
0096 MODULE_PARM_DESC(irq, "IRQ of the Applicom board");
0097 module_param_hw(mem, ulong, iomem, 0);
0098 MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board");
0099 
0100 static unsigned int numboards;  /* number of installed boards */
0101 static volatile unsigned char Dummy;
0102 static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec);
0103 static unsigned int WriteErrorCount;    /* number of write error      */
0104 static unsigned int ReadErrorCount; /* number of read error       */
0105 static unsigned int DeviceErrorCount;   /* number of device error     */
0106 
0107 static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *);
0108 static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *);
0109 static long ac_ioctl(struct file *, unsigned int, unsigned long);
0110 static irqreturn_t ac_interrupt(int, void *);
0111 
0112 static const struct file_operations ac_fops = {
0113     .owner = THIS_MODULE,
0114     .llseek = no_llseek,
0115     .read = ac_read,
0116     .write = ac_write,
0117     .unlocked_ioctl = ac_ioctl,
0118 };
0119 
0120 static struct miscdevice ac_miscdev = {
0121     AC_MINOR,
0122     "ac",
0123     &ac_fops
0124 };
0125 
0126 static int dummy;   /* dev_id for request_irq() */
0127 
0128 static int ac_register_board(unsigned long physloc, void __iomem *loc, 
0129               unsigned char boardno)
0130 {
0131     volatile unsigned char byte_reset_it;
0132 
0133     if((readb(loc + CONF_END_TEST)     != 0x00) ||
0134        (readb(loc + CONF_END_TEST + 1) != 0x55) ||
0135        (readb(loc + CONF_END_TEST + 2) != 0xAA) ||
0136        (readb(loc + CONF_END_TEST + 3) != 0xFF))
0137         return 0;
0138 
0139     if (!boardno)
0140         boardno = readb(loc + NUMCARD_OWNER_TO_PC);
0141 
0142     if (!boardno || boardno > MAX_BOARD) {
0143         printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",
0144                boardno, physloc, MAX_BOARD);
0145         return 0;
0146     }
0147 
0148     if (apbs[boardno - 1].RamIO) {
0149         printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", 
0150                boardno, physloc, boardno, apbs[boardno-1].PhysIO);
0151         return 0;
0152     }
0153 
0154     boardno--;
0155 
0156     apbs[boardno].PhysIO = physloc;
0157     apbs[boardno].RamIO = loc;
0158     init_waitqueue_head(&apbs[boardno].FlagSleepSend);
0159     spin_lock_init(&apbs[boardno].mutex);
0160     byte_reset_it = readb(loc + RAM_IT_TO_PC);
0161 
0162     numboards++;
0163     return boardno + 1;
0164 }
0165 
0166 static void __exit applicom_exit(void)
0167 {
0168     unsigned int i;
0169 
0170     misc_deregister(&ac_miscdev);
0171 
0172     for (i = 0; i < MAX_BOARD; i++) {
0173 
0174         if (!apbs[i].RamIO)
0175             continue;
0176 
0177         if (apbs[i].irq)
0178             free_irq(apbs[i].irq, &dummy);
0179 
0180         iounmap(apbs[i].RamIO);
0181     }
0182 }
0183 
0184 static int __init applicom_init(void)
0185 {
0186     int i, numisa = 0;
0187     struct pci_dev *dev = NULL;
0188     void __iomem *RamIO;
0189     int boardno, ret;
0190 
0191     printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
0192 
0193     /* No mem and irq given - check for a PCI card */
0194 
0195     while ( (dev = pci_get_class(PCI_CLASS_OTHERS << 16, dev))) {
0196 
0197         if (!pci_match_id(applicom_pci_tbl, dev))
0198             continue;
0199         
0200         if (pci_enable_device(dev))
0201             return -EIO;
0202 
0203         RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO);
0204 
0205         if (!RamIO) {
0206             printk(KERN_INFO "ac.o: Failed to ioremap PCI memory "
0207                 "space at 0x%llx\n",
0208                 (unsigned long long)pci_resource_start(dev, 0));
0209             pci_disable_device(dev);
0210             return -EIO;
0211         }
0212 
0213         printk(KERN_INFO "Applicom %s found at mem 0x%llx, irq %d\n",
0214                applicom_pci_devnames[dev->device-1],
0215                (unsigned long long)pci_resource_start(dev, 0),
0216                dev->irq);
0217 
0218         boardno = ac_register_board(pci_resource_start(dev, 0),
0219                 RamIO, 0);
0220         if (!boardno) {
0221             printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
0222             iounmap(RamIO);
0223             pci_disable_device(dev);
0224             continue;
0225         }
0226 
0227         if (request_irq(dev->irq, &ac_interrupt, IRQF_SHARED, "Applicom PCI", &dummy)) {
0228             printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
0229             iounmap(RamIO);
0230             pci_disable_device(dev);
0231             apbs[boardno - 1].RamIO = NULL;
0232             continue;
0233         }
0234 
0235         /* Enable interrupts. */
0236 
0237         writeb(0x40, apbs[boardno - 1].RamIO + RAM_IT_FROM_PC);
0238 
0239         apbs[boardno - 1].irq = dev->irq;
0240     }
0241 
0242     /* Finished with PCI cards. If none registered, 
0243      * and there was no mem/irq specified, exit */
0244 
0245     if (!mem || !irq) {
0246         if (numboards)
0247             goto fin;
0248         else {
0249             printk(KERN_INFO "ac.o: No PCI boards found.\n");
0250             printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n");
0251             return -ENXIO;
0252         }
0253     }
0254 
0255     /* Now try the specified ISA cards */
0256 
0257     for (i = 0; i < MAX_ISA_BOARD; i++) {
0258         RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
0259 
0260         if (!RamIO) {
0261             printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1);
0262             continue;
0263         }
0264 
0265         if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
0266                           RamIO,i+1))) {
0267             iounmap(RamIO);
0268             continue;
0269         }
0270 
0271         printk(KERN_NOTICE "Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq);
0272 
0273         if (!numisa) {
0274             if (request_irq(irq, &ac_interrupt, IRQF_SHARED, "Applicom ISA", &dummy)) {
0275                 printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq);
0276                 iounmap(RamIO);
0277                 apbs[boardno - 1].RamIO = NULL;
0278             }
0279             else
0280                 apbs[boardno - 1].irq = irq;
0281         }
0282         else
0283             apbs[boardno - 1].irq = 0;
0284 
0285         numisa++;
0286     }
0287 
0288     if (!numisa)
0289         printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found "
0290                 "at mem 0x%lx\n", mem);
0291 
0292  fin:
0293     init_waitqueue_head(&FlagSleepRec);
0294 
0295     WriteErrorCount = 0;
0296     ReadErrorCount = 0;
0297     DeviceErrorCount = 0;
0298 
0299     if (numboards) {
0300         ret = misc_register(&ac_miscdev);
0301         if (ret) {
0302             printk(KERN_WARNING "ac.o: Unable to register misc device\n");
0303             goto out;
0304         }
0305         for (i = 0; i < MAX_BOARD; i++) {
0306             int serial;
0307             char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
0308 
0309             if (!apbs[i].RamIO)
0310                 continue;
0311 
0312             for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
0313                 boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
0314 
0315             boardname[serial] = 0;
0316 
0317 
0318             printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d",
0319                    i+1, boardname,
0320                    (int)(readb(apbs[i].RamIO + VERS) >> 4),
0321                    (int)(readb(apbs[i].RamIO + VERS) & 0xF));
0322             
0323             serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + 
0324                 (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + 
0325                 (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
0326 
0327             if (serial != 0)
0328                 printk(" S/N %d\n", serial);
0329             else
0330                 printk("\n");
0331         }
0332         return 0;
0333     }
0334 
0335     else
0336         return -ENXIO;
0337 
0338 out:
0339     for (i = 0; i < MAX_BOARD; i++) {
0340         if (!apbs[i].RamIO)
0341             continue;
0342         if (apbs[i].irq)
0343             free_irq(apbs[i].irq, &dummy);
0344         iounmap(apbs[i].RamIO);
0345     }
0346     return ret;
0347 }
0348 
0349 module_init(applicom_init);
0350 module_exit(applicom_exit);
0351 
0352 
0353 static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
0354 {
0355     unsigned int NumCard;   /* Board number 1 -> 8           */
0356     unsigned int IndexCard; /* Index board number 0 -> 7     */
0357     unsigned char TicCard;  /* Board TIC to send             */
0358     unsigned long flags;    /* Current priority              */
0359     struct st_ram_io st_loc;
0360     struct mailbox tmpmailbox;
0361 #ifdef DEBUG
0362     int c;
0363 #endif
0364     DECLARE_WAITQUEUE(wait, current);
0365 
0366     if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
0367         static int warncount = 5;
0368         if (warncount) {
0369             printk(KERN_INFO "Hmmm. write() of Applicom card, length %zd != expected %zd\n",
0370                    count, sizeof(struct st_ram_io) + sizeof(struct mailbox));
0371             warncount--;
0372         }
0373         return -EINVAL;
0374     }
0375 
0376     if(copy_from_user(&st_loc, buf, sizeof(struct st_ram_io))) 
0377         return -EFAULT;
0378     
0379     if(copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)],
0380               sizeof(struct mailbox))) 
0381         return -EFAULT;
0382 
0383     NumCard = st_loc.num_card;  /* board number to send          */
0384     TicCard = st_loc.tic_des_from_pc;   /* tic number to send            */
0385     IndexCard = NumCard - 1;
0386 
0387     if (IndexCard >= MAX_BOARD)
0388         return -EINVAL;
0389     IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
0390 
0391     if (!apbs[IndexCard].RamIO)
0392         return -EINVAL;
0393 
0394 #ifdef DEBUG
0395     printk("Write to applicom card #%d. struct st_ram_io follows:",
0396            IndexCard+1);
0397 
0398         for (c = 0; c < sizeof(struct st_ram_io);) {
0399         
0400             printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]);
0401 
0402             for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {
0403                 printk(" %2.2X", ((unsigned char *) &st_loc)[c]);
0404             }
0405         }
0406 
0407         printk("\nstruct mailbox follows:");
0408 
0409         for (c = 0; c < sizeof(struct mailbox);) {
0410             printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]);
0411 
0412             for (c++; c % 8 && c < sizeof(struct mailbox); c++) {
0413                 printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]);
0414             }
0415         }
0416 
0417         printk("\n");
0418 #endif
0419 
0420     spin_lock_irqsave(&apbs[IndexCard].mutex, flags);
0421 
0422     /* Test octet ready correct */
0423     if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) { 
0424         Dummy = readb(apbs[IndexCard].RamIO + VERS);
0425         spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
0426         printk(KERN_WARNING "APPLICOM driver write error board %d, DataFromPcReady = %d\n",
0427                IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY));
0428         DeviceErrorCount++;
0429         return -EIO;
0430     }
0431     
0432     /* Place ourselves on the wait queue */
0433     set_current_state(TASK_INTERRUPTIBLE);
0434     add_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait);
0435 
0436     /* Check whether the card is ready for us */
0437     while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) {
0438         Dummy = readb(apbs[IndexCard].RamIO + VERS);
0439         /* It's busy. Sleep. */
0440 
0441         spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
0442         schedule();
0443         if (signal_pending(current)) {
0444             remove_wait_queue(&apbs[IndexCard].FlagSleepSend,
0445                       &wait);
0446             return -EINTR;
0447         }
0448         spin_lock_irqsave(&apbs[IndexCard].mutex, flags);
0449         set_current_state(TASK_INTERRUPTIBLE);
0450     }
0451 
0452     /* We may not have actually slept */
0453     set_current_state(TASK_RUNNING);
0454     remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait);
0455 
0456     writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
0457 
0458     /* Which is best - lock down the pages with rawio and then
0459        copy directly, or use bounce buffers? For now we do the latter 
0460        because it works with 2.2 still */
0461     {
0462         unsigned char *from = (unsigned char *) &tmpmailbox;
0463         void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC;
0464         int c;
0465 
0466         for (c = 0; c < sizeof(struct mailbox); c++)
0467             writeb(*(from++), to++);
0468     }
0469 
0470     writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC);
0471     writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC);
0472     writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC);
0473     writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
0474     writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
0475     writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
0476     Dummy = readb(apbs[IndexCard].RamIO + VERS);
0477     spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags);
0478     return 0;
0479 }
0480 
0481 static int do_ac_read(int IndexCard, char __user *buf,
0482         struct st_ram_io *st_loc, struct mailbox *mailbox)
0483 {
0484     void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
0485     unsigned char *to = (unsigned char *)mailbox;
0486 #ifdef DEBUG
0487     int c;
0488 #endif
0489 
0490     st_loc->tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
0491     st_loc->numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
0492 
0493 
0494     {
0495         int c;
0496 
0497         for (c = 0; c < sizeof(struct mailbox); c++)
0498             *(to++) = readb(from++);
0499     }
0500     writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
0501     writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC);
0502     writeb(IndexCard+1, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
0503     writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), 
0504            apbs[IndexCard].RamIO + TIC_ACK_FROM_PC);
0505     writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
0506     writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY);
0507     writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
0508     Dummy = readb(apbs[IndexCard].RamIO + VERS);
0509 
0510 #ifdef DEBUG
0511         printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard);
0512 
0513         for (c = 0; c < sizeof(struct st_ram_io);) {
0514             printk("\n%5.5X: %2.2X", c, ((unsigned char *)st_loc)[c]);
0515 
0516             for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {
0517                 printk(" %2.2X", ((unsigned char *)st_loc)[c]);
0518             }
0519         }
0520 
0521         printk("\nstruct mailbox follows:");
0522 
0523         for (c = 0; c < sizeof(struct mailbox);) {
0524             printk("\n%5.5X: %2.2X", c, ((unsigned char *)mailbox)[c]);
0525 
0526             for (c++; c % 8 && c < sizeof(struct mailbox); c++) {
0527                 printk(" %2.2X", ((unsigned char *)mailbox)[c]);
0528             }
0529         }
0530         printk("\n");
0531 #endif
0532     return (sizeof(struct st_ram_io) + sizeof(struct mailbox));
0533 }
0534 
0535 static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_t *ptr)
0536 {
0537     unsigned long flags;
0538     unsigned int i;
0539     unsigned char tmp;
0540     int ret = 0;
0541     DECLARE_WAITQUEUE(wait, current);
0542 #ifdef DEBUG
0543     int loopcount=0;
0544 #endif
0545     /* No need to ratelimit this. Only root can trigger it anyway */
0546     if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
0547         printk( KERN_WARNING "Hmmm. read() of Applicom card, length %zd != expected %zd\n",
0548             count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
0549         return -EINVAL;
0550     }
0551     
0552     while(1) {
0553         /* Stick ourself on the wait queue */
0554         set_current_state(TASK_INTERRUPTIBLE);
0555         add_wait_queue(&FlagSleepRec, &wait);
0556         
0557         /* Scan each board, looking for one which has a packet for us */
0558         for (i=0; i < MAX_BOARD; i++) {
0559             if (!apbs[i].RamIO)
0560                 continue;
0561             spin_lock_irqsave(&apbs[i].mutex, flags);
0562             
0563             tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);
0564             
0565             if (tmp == 2) {
0566                 struct st_ram_io st_loc;
0567                 struct mailbox mailbox;
0568 
0569                 /* Got a packet for us */
0570                 memset(&st_loc, 0, sizeof(st_loc));
0571                 ret = do_ac_read(i, buf, &st_loc, &mailbox);
0572                 spin_unlock_irqrestore(&apbs[i].mutex, flags);
0573                 set_current_state(TASK_RUNNING);
0574                 remove_wait_queue(&FlagSleepRec, &wait);
0575 
0576                 if (copy_to_user(buf, &st_loc, sizeof(st_loc)))
0577                     return -EFAULT;
0578                 if (copy_to_user(buf + sizeof(st_loc), &mailbox, sizeof(mailbox)))
0579                     return -EFAULT;
0580                 return tmp;
0581             }
0582             
0583             if (tmp > 2) {
0584                 /* Got an error */
0585                 Dummy = readb(apbs[i].RamIO + VERS);
0586                 
0587                 spin_unlock_irqrestore(&apbs[i].mutex, flags);
0588                 set_current_state(TASK_RUNNING);
0589                 remove_wait_queue(&FlagSleepRec, &wait);
0590                 
0591                 printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n",
0592                        i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
0593                 DeviceErrorCount++;
0594                 return -EIO;
0595             }
0596             
0597             /* Nothing for us. Try the next board */
0598             Dummy = readb(apbs[i].RamIO + VERS);
0599             spin_unlock_irqrestore(&apbs[i].mutex, flags);
0600             
0601         } /* per board */
0602 
0603         /* OK - No boards had data for us. Sleep now */
0604 
0605         schedule();
0606         remove_wait_queue(&FlagSleepRec, &wait);
0607 
0608         if (signal_pending(current))
0609             return -EINTR;
0610 
0611 #ifdef DEBUG
0612         if (loopcount++ > 2) {
0613             printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
0614         }
0615 #endif
0616     } 
0617 }
0618 
0619 static irqreturn_t ac_interrupt(int vec, void *dev_instance)
0620 {
0621     unsigned int i;
0622     unsigned int FlagInt;
0623     unsigned int LoopCount;
0624     int handled = 0;
0625 
0626     //    printk("Applicom interrupt on IRQ %d occurred\n", vec);
0627 
0628     LoopCount = 0;
0629 
0630     do {
0631         FlagInt = 0;
0632         for (i = 0; i < MAX_BOARD; i++) {
0633             
0634             /* Skip if this board doesn't exist */
0635             if (!apbs[i].RamIO)
0636                 continue;
0637 
0638             spin_lock(&apbs[i].mutex);
0639 
0640             /* Skip if this board doesn't want attention */
0641             if(readb(apbs[i].RamIO + RAM_IT_TO_PC) == 0) {
0642                 spin_unlock(&apbs[i].mutex);
0643                 continue;
0644             }
0645 
0646             handled = 1;
0647             FlagInt = 1;
0648             writeb(0, apbs[i].RamIO + RAM_IT_TO_PC);
0649 
0650             if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) {
0651                 printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n",
0652                        i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
0653                 DeviceErrorCount++;
0654             }
0655 
0656             if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && 
0657                (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) {
0658                 
0659                 printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n",
0660                        i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY));
0661                 DeviceErrorCount++;
0662             }
0663 
0664             if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { /* mailbox sent by the card ?   */
0665                 if (waitqueue_active(&FlagSleepRec)) {
0666                 wake_up_interruptible(&FlagSleepRec);
0667             }
0668             }
0669 
0670             if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) {   /* ram i/o free for write by pc ? */
0671                 if (waitqueue_active(&apbs[i].FlagSleepSend)) { /* process sleep during read ?    */
0672                     wake_up_interruptible(&apbs[i].FlagSleepSend);
0673                 }
0674             }
0675             Dummy = readb(apbs[i].RamIO + VERS);
0676 
0677             if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) {
0678                 /* There's another int waiting on this card */
0679                 spin_unlock(&apbs[i].mutex);
0680                 i--;
0681             } else {
0682                 spin_unlock(&apbs[i].mutex);
0683             }
0684         }
0685         if (FlagInt)
0686             LoopCount = 0;
0687         else
0688             LoopCount++;
0689     } while(LoopCount < 2);
0690     return IRQ_RETVAL(handled);
0691 }
0692 
0693 
0694 
0695 static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0696      
0697 {               /* @ ADG ou ATO selon le cas */
0698     int i;
0699     unsigned char IndexCard;
0700     void __iomem *pmem;
0701     int ret = 0;
0702     static int warncount = 10;
0703     volatile unsigned char byte_reset_it;
0704     struct st_ram_io *adgl;
0705     void __user *argp = (void __user *)arg;
0706 
0707     /* In general, the device is only openable by root anyway, so we're not
0708        particularly concerned that bogus ioctls can flood the console. */
0709 
0710     adgl = memdup_user(argp, sizeof(struct st_ram_io));
0711     if (IS_ERR(adgl))
0712         return PTR_ERR(adgl);
0713 
0714     mutex_lock(&ac_mutex);  
0715     IndexCard = adgl->num_card-1;
0716      
0717     if (cmd != 6 && IndexCard >= MAX_BOARD)
0718         goto err;
0719     IndexCard = array_index_nospec(IndexCard, MAX_BOARD);
0720 
0721     if (cmd != 6 && !apbs[IndexCard].RamIO)
0722         goto err;
0723 
0724     switch (cmd) {
0725         
0726     case 0:
0727         pmem = apbs[IndexCard].RamIO;
0728         for (i = 0; i < sizeof(struct st_ram_io); i++)
0729             ((unsigned char *)adgl)[i]=readb(pmem++);
0730         if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
0731             ret = -EFAULT;
0732         break;
0733     case 1:
0734         pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
0735         for (i = 0; i < 4; i++)
0736             adgl->conf_end_test[i] = readb(pmem++);
0737         for (i = 0; i < 2; i++)
0738             adgl->error_code[i] = readb(pmem++);
0739         for (i = 0; i < 4; i++)
0740             adgl->parameter_error[i] = readb(pmem++);
0741         pmem = apbs[IndexCard].RamIO + VERS;
0742         adgl->vers = readb(pmem);
0743         pmem = apbs[IndexCard].RamIO + TYPE_CARD;
0744         for (i = 0; i < 20; i++)
0745             adgl->reserv1[i] = readb(pmem++);
0746         *(int *)&adgl->reserv1[20] =  
0747             (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + 
0748             (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + 
0749             (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );
0750 
0751         if (copy_to_user(argp, adgl, sizeof(struct st_ram_io)))
0752             ret = -EFAULT;
0753         break;
0754     case 2:
0755         pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
0756         for (i = 0; i < 10; i++)
0757             writeb(0xff, pmem++);
0758         writeb(adgl->data_from_pc_ready, 
0759                apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
0760 
0761         writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
0762         
0763         for (i = 0; i < MAX_BOARD; i++) {
0764             if (apbs[i].RamIO) {
0765                 byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC);
0766             }
0767         }
0768         break;
0769     case 3:
0770         pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;
0771         writeb(adgl->tic_des_from_pc, pmem);
0772         break;
0773     case 4:
0774         pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
0775         adgl->tic_owner_to_pc     = readb(pmem++);
0776         adgl->numcard_owner_to_pc = readb(pmem);
0777         if (copy_to_user(argp, adgl,sizeof(struct st_ram_io)))
0778             ret = -EFAULT;
0779         break;
0780     case 5:
0781         writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
0782         writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
0783         writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
0784         writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
0785         writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
0786         break;
0787     case 6:
0788         printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n");
0789         printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards);
0790         printk(KERN_INFO "Segment of board ........... %X\n", (int) mem);
0791         printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq);
0792         for (i = 0; i < MAX_BOARD; i++) {
0793             int serial;
0794             char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
0795 
0796             if (!apbs[i].RamIO)
0797                 continue;
0798 
0799             for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
0800                 boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
0801             boardname[serial] = 0;
0802 
0803             printk(KERN_INFO "Prom version board %d ....... V%d.%d %s",
0804                    i+1,
0805                    (int)(readb(apbs[i].RamIO + VERS) >> 4),
0806                    (int)(readb(apbs[i].RamIO + VERS) & 0xF),
0807                    boardname);
0808 
0809 
0810             serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + 
0811                 (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + 
0812                 (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
0813 
0814             if (serial != 0)
0815                 printk(" S/N %d\n", serial);
0816             else
0817                 printk("\n");
0818         }
0819         if (DeviceErrorCount != 0)
0820             printk(KERN_INFO "DeviceErrorCount ........... %d\n", DeviceErrorCount);
0821         if (ReadErrorCount != 0)
0822             printk(KERN_INFO "ReadErrorCount ............. %d\n", ReadErrorCount);
0823         if (WriteErrorCount != 0)
0824             printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount);
0825         if (waitqueue_active(&FlagSleepRec))
0826             printk(KERN_INFO "Process in read pending\n");
0827         for (i = 0; i < MAX_BOARD; i++) {
0828             if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend))
0829                 printk(KERN_INFO "Process in write pending board %d\n",i+1);
0830         }
0831         break;
0832     default:
0833         ret = -ENOTTY;
0834         break;
0835     }
0836     Dummy = readb(apbs[IndexCard].RamIO + VERS);
0837     kfree(adgl);
0838     mutex_unlock(&ac_mutex);
0839     return ret;
0840 
0841 err:
0842     if (warncount) {
0843         pr_warn("APPLICOM driver IOCTL, bad board number %d\n",
0844             (int)IndexCard + 1);
0845         warncount--;
0846     }
0847     kfree(adgl);
0848     mutex_unlock(&ac_mutex);
0849     return -EINVAL;
0850 
0851 }
0852