/* The typical workload of the driver: Handle the ether interface interrupts. */ static void el_interrupt(int reg_ptr) { int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); /*struct device *dev = (struct device *)(irq2dev_map[irq]);*/ struct device *dev = eldev; int axsr; /* Aux. status reg. */ short ioaddr; if (eldev->irq != irq) { printk (EL_NAME ": irq %d for unknown device\n", irq); return; } ioaddr = dev->base_addr; axsr = inb(AX_STATUS); if (el_debug > 3) printk("%s: el_interrupt() aux=%#02x", dev->name, axsr); if (dev->interrupt) printk("%s: Reentering the interrupt driver!\n", dev->name); dev->interrupt = 1; if (dev->tbusy) { int txsr = inb(TX_STATUS); if (el_debug > 6) printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW), inw(RX_LOW)); if ((axsr & 0x80) && (txsr & TX_READY) == 0) { printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); dev->tbusy = 0; mark_bh(INET_BH); } else if (txsr & TX_16COLLISIONS) { if (el_debug) printk("%s: Transmit failed 16 times, ethernet jammed?\n", dev->name); outb(AX_SYS, AX_CMD); el_status.stats.tx_aborted_errors++; } else if (txsr & TX_COLLISION) { /* Retrigger xmit. */ if (el_debug > 6) printk(" retransmitting after a collision.\n"); outb(AX_SYS, AX_CMD); outw(el_status.tx_pkt_start, GP_LOW); outb(AX_XMIT, AX_CMD); el_status.stats.collisions++; dev->interrupt = 0; return; } else { el_status.stats.tx_packets++; if (el_debug > 6) printk(" Tx succeeded %s\n", (txsr & TX_RDY) ? "." : "but tx is busy!"); dev->tbusy = 0; mark_bh(INET_BH); } } else { int rxsr = inb(RX_STATUS); if (el_debug > 5) printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS), inw(RX_LOW)); /* Just reading rx_status fixes most errors. */ if (rxsr & RX_MISSED) el_status.stats.rx_missed_errors++; if (rxsr & RX_RUNT) { /* Handled to avoid board lock-up. */ el_status.stats.rx_length_errors++; if (el_debug > 5) printk(" runt.\n"); } else if (rxsr & RX_GOOD) { el_receive(eldev); } else { /* Nothing? Something is broken! */ if (el_debug > 2) printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", dev->name, rxsr); el_reset(eldev); } if (el_debug > 3) printk(".\n"); } outb(AX_RX, AX_CMD); outb(0x00, RX_BUF_CLR); inb(RX_STATUS); /* Be certain that interrupts are cleared. */ inb(TX_STATUS); dev->interrupt = 0; return; }
static irqreturn_t el_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct net_local *lp; int ioaddr; int axsr; /* Aux. status reg. */ ioaddr = dev->base_addr; lp = netdev_priv(dev); spin_lock(&lp->lock); /* * What happened ? */ axsr = inb(AX_STATUS); /* * Log it */ if (el_debug > 3) pr_debug("%s: el_interrupt() aux=%#02x\n", dev->name, axsr); if (lp->loading == 1 && !lp->txing) pr_warning("%s: Inconsistent state loading while not in tx\n", dev->name); if (lp->txing) { /* * Board in transmit mode. May be loading. If we are * loading we shouldn't have got this. */ int txsr = inb(TX_STATUS); if (lp->loading == 1) { if (el_debug > 2) pr_debug("%s: Interrupt while loading [txsr=%02x gp=%04x rp=%04x]\n", dev->name, txsr, inw(GP_LOW), inw(RX_LOW)); /* Force a reload */ lp->loading = 2; spin_unlock(&lp->lock); goto out; } if (el_debug > 6) pr_debug("%s: txsr=%02x gp=%04x rp=%04x\n", dev->name, txsr, inw(GP_LOW), inw(RX_LOW)); if ((axsr & 0x80) && (txsr & TX_READY) == 0) { /* * FIXME: is there a logic to whether to keep * on trying or reset immediately ? */ if (el_debug > 1) pr_debug("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); lp->txing = 0; netif_wake_queue(dev); } else if (txsr & TX_16COLLISIONS) { /* * Timed out */ if (el_debug) pr_debug("%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name); outb(AX_SYS, AX_CMD); lp->txing = 0; dev->stats.tx_aborted_errors++; netif_wake_queue(dev); } else if (txsr & TX_COLLISION) { /* * Retrigger xmit. */ if (el_debug > 6) pr_debug("%s: retransmitting after a collision.\n", dev->name); /* * Poor little chip can't reset its own start * pointer */ outb(AX_SYS, AX_CMD); outw(lp->tx_pkt_start, GP_LOW); outb(AX_XMIT, AX_CMD); dev->stats.collisions++; spin_unlock(&lp->lock); goto out; } else { /* * It worked.. we will now fall through and receive */ dev->stats.tx_packets++; if (el_debug > 6) pr_debug("%s: Tx succeeded %s\n", dev->name, (txsr & TX_RDY) ? "." : "but tx is busy!"); /* * This is safe the interrupt is atomic WRT itself. */ lp->txing = 0; /* In case more to transmit */ netif_wake_queue(dev); } } else { /* * In receive mode. */ int rxsr = inb(RX_STATUS); if (el_debug > 5) pr_debug("%s: rxsr=%02x txsr=%02x rp=%04x\n", dev->name, rxsr, inb(TX_STATUS), inw(RX_LOW)); /* * Just reading rx_status fixes most errors. */ if (rxsr & RX_MISSED) dev->stats.rx_missed_errors++; else if (rxsr & RX_RUNT) { /* Handled to avoid board lock-up. */ dev->stats.rx_length_errors++; if (el_debug > 5) pr_debug("%s: runt.\n", dev->name); } else if (rxsr & RX_GOOD) { /* * Receive worked. */ el_receive(dev); } else { /* * Nothing? Something is broken! */ if (el_debug > 2) pr_debug("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", dev->name, rxsr); el_reset(dev); } } /* * Move into receive mode */ outb(AX_RX, AX_CMD); outw(0x00, RX_BUF_CLR); inb(RX_STATUS); /* Be certain that interrupts are cleared. */ inb(TX_STATUS); spin_unlock(&lp->lock); out: return IRQ_HANDLED; }
static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)(irq2dev_map[irq]); struct net_local *lp; int ioaddr; int axsr; /* Aux. status reg. */ if (dev == NULL || dev->irq != irq) { printk ("3c501 driver: irq %d for unknown device.\n", irq); return; } ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; /* * What happened ? */ axsr = inb(AX_STATUS); /* * Log it */ if (el_debug > 3) printk("%s: el_interrupt() aux=%#02x", dev->name, axsr); if (dev->interrupt) printk("%s: Reentering the interrupt driver!\n", dev->name); dev->interrupt = 1; #ifndef BLOCKOUT_1 if(lp->loading==1 && !dev->tbusy) printk("%s: Inconsistent state loading while not in tx\n", dev->name); #endif #ifdef BLOCKOUT_3 lp->loading=2; /* So we can spot loading interruptions */ #endif if (dev->tbusy) { /* * Board in transmit mode. May be loading. If we are * loading we shouldn't have got this. */ int txsr = inb(TX_STATUS); #ifdef BLOCKOUT_2 if(lp->loading==1) { if(el_debug > 2) { printk("%s: Interrupt while loading [", dev->name); printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); } lp->loading=2; /* Force a reload */ dev->interrupt = 0; return; } #endif if (el_debug > 6) printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW)); if ((axsr & 0x80) && (txsr & TX_READY) == 0) { /* * FIXME: is there a logic to whether to keep on trying or * reset immediately ? */ if(el_debug>1) printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); dev->tbusy = 0; mark_bh(NET_BH); } else if (txsr & TX_16COLLISIONS) { /* * Timed out */ if (el_debug) printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name); outb(AX_SYS, AX_CMD); lp->stats.tx_aborted_errors++; } else if (txsr & TX_COLLISION) { /* * Retrigger xmit. */ if (el_debug > 6) printk(" retransmitting after a collision.\n"); /* * Poor little chip can't reset its own start pointer */ outb(AX_SYS, AX_CMD); outw(lp->tx_pkt_start, GP_LOW); outb(AX_XMIT, AX_CMD); lp->stats.collisions++; dev->interrupt = 0; return; } else { /* * It worked.. we will now fall through and receive */ lp->stats.tx_packets++; if (el_debug > 6) printk(" Tx succeeded %s\n", (txsr & TX_RDY) ? "." : "but tx is busy!"); /* * This is safe the interrupt is atomic WRT itself. */ dev->tbusy = 0; mark_bh(NET_BH); /* In case more to transmit */ } } else { /* * In receive mode. */ int rxsr = inb(RX_STATUS); if (el_debug > 5) printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW)); /* * Just reading rx_status fixes most errors. */ if (rxsr & RX_MISSED) lp->stats.rx_missed_errors++; else if (rxsr & RX_RUNT) { /* Handled to avoid board lock-up. */ lp->stats.rx_length_errors++; if (el_debug > 5) printk(" runt.\n"); } else if (rxsr & RX_GOOD) { /* * Receive worked. */ el_receive(dev); } else { /* * Nothing? Something is broken! */ if (el_debug > 2) printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", dev->name, rxsr); el_reset(dev); } if (el_debug > 3) printk(".\n"); } /* * Move into receive mode */ outb(AX_RX, AX_CMD); outw(0x00, RX_BUF_CLR); inb(RX_STATUS); /* Be certain that interrupts are cleared. */ inb(TX_STATUS); dev->interrupt = 0; return; }