Exemple #1
0
/* 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;
}
Exemple #3
0
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;
}