shared irq patch for de4x5

Robin Cutshaw (robin@intercore.com)
Wed, 21 Feb 1996 16:55:53 -0500 (EST)


One of my systems (a Dell P75) assigns shared irq's between two 21040 based
boards. As the driver (de4x5) does not currently support shared irq's,
I've added it. Here's the patch. Shared irq's should really be
handled at a higher level than the driver but until the irq setup
code is reworked, this will have to do...

robin

--
----
Robin Cutshaw         internet: robin@interlabs.com robin@intercore.com
Internet Labs, Inc.   BellNet:  404-817-9787

"Time is just one damn thing after another" -- PBS/Nova ----

--

*** de4x5.c.ORIG Thu Dec 14 23:46:15 1995 --- de4x5.c Tue Feb 20 22:38:58 1996 *************** *** 458,463 **** --- 458,466 ---- static char name[DE4X5_NAME_LENGTH + 1]; static int num_de4x5s = 0, num_eth = 0; + #define MAX_DE4X5_DEVS 16 + static struct device *de4x5_devs[MAX_DE4X5_DEVS]; + /* ** Kludge to get around the fact that the CSR addresses have different ** offsets in the PCI and EISA boards. Also note that the ethernet address *************** *** 525,530 **** --- 528,540 ---- struct bus_type *lp = &bus; int tmpbus, tmpchs, i, j, status=0; char *tmp; + static int de4x5_devs_inited = 0; + + if (!de4x5_devs_inited) { + for (i=0; i<MAX_DE4X5_DEVS; i++) + de4x5_devs[i] = 0; + de4x5_devs_inited = 1; + } /* Ensure we're not sleeping */ if (lp->chipset == DC21041) { *************** *** 762,772 **** } if (request_irq(dev->irq, (void *)de4x5_interrupt, 0, lp->adapter_name)) { ! printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq); ! status = -EAGAIN; ! } else { ! irq2dev_map[dev->irq] = dev; /* ** Re-initialize the DE4X5... */ --- 772,806 ---- } if (request_irq(dev->irq, (void *)de4x5_interrupt, 0, lp->adapter_name)) { ! for (i=0; i<MAX_DE4X5_DEVS; i++) ! if ((de4x5_devs[i] != 0) && (de4x5_devs[i]->irq == dev->irq)) ! break; /* dup irq */ ! if (i == MAX_DE4X5_DEVS) { ! printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq); ! status = -EAGAIN; ! } ! } else irq2dev_map[dev->irq] = dev; + + if (!status) { + /* put the device in our private device array */ + for (i=0; i<MAX_DE4X5_DEVS; i++) + if (de4x5_devs[i] == dev) + break; /* already there */ + if (i == MAX_DE4X5_DEVS) { /* not found */ + for (i=0; i<MAX_DE4X5_DEVS; i++) + if (de4x5_devs[i] == 0) { + de4x5_devs[i] = dev; + break; + } + if (i == MAX_DE4X5_DEVS) { /* no more room */ + printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq); + status = -EAGAIN; + } + } + } + + if (!status) { /* ** Re-initialize the DE4X5... */ *************** *** 1067,1080 **** static void de4x5_interrupt(int irq, struct pt_regs *regs) { ! struct device *dev = (struct device *)(irq2dev_map[irq]); struct de4x5_private *lp; s32 imr, omr, sts; u_long iobase; ! if (dev == NULL) { ! printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq); ! } else { lp = (struct de4x5_private *)dev->priv; iobase = dev->base_addr; --- 1101,1120 ---- static void de4x5_interrupt(int irq, struct pt_regs *regs) { ! struct device *dev; struct de4x5_private *lp; s32 imr, omr, sts; u_long iobase; + int i, devs_processed = 0; ! for (i=0; i<MAX_DE4X5_DEVS; i++) { ! if ((de4x5_devs[i] == 0) || (de4x5_devs[i]->irq != irq)) ! continue; ! ! /* found an irq that matched */ ! devs_processed++; ! ! dev = de4x5_devs[i]; lp = (struct de4x5_private *)dev->priv; iobase = dev->base_addr; *************** *** 1118,1123 **** --- 1158,1166 ---- ENABLE_IRQs; } + if (devs_processed == 0) + printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq); + return; } *************** *** 1313,1318 **** --- 1356,1362 ---- struct de4x5_private *lp = (struct de4x5_private *)dev->priv; u_long iobase = dev->base_addr; s32 imr, omr; + int i; dev->start = 0; dev->tbusy = 1; *************** *** 1329,1339 **** STOP_DE4X5; ! /* ! ** Free the associated irq ! */ ! free_irq(dev->irq); ! irq2dev_map[dev->irq] = 0; MOD_DEC_USE_COUNT; --- 1373,1391 ---- STOP_DE4X5; ! for (i=0; i<MAX_DE4X5_DEVS; i++) ! if ((de4x5_devs[i] != 0) && ! (de4x5_devs[i] != dev) && ! (de4x5_devs[i]->irq == dev->irq)) ! break; /* dup irq, don't free it */ ! ! if (i == MAX_DE4X5_DEVS) { /* no dup irqs */ ! /* ! ** Free the associated irq ! */ ! free_irq(dev->irq); ! irq2dev_map[dev->irq] = 0; ! } MOD_DEC_USE_COUNT;