kernels/linux-2.4.0/drivers/net/dmfe.c
/*
   DM9102 insterrupt handler
   receive the packet to upper layer, free the transmitted packet
 */
DM9102 insterrupt handler
receive the packet to upper layer, free the transmitted packet
DM9102 insterrupt handler receive the packet to upper layer free the transmitted packet
static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	struct net_device *dev = dev_id;
	struct tx_desc *txptr;
	struct dmfe_board_info *db;
	u32 ioaddr;
	if (!dev) {
		DMFE_DBUG(1, "dmfe_interrupt() without device arg", 0);
		return;
	}
	db = (struct dmfe_board_info *) dev->priv;
	ioaddr = dev->base_addr;
	DMFE_DBUG(0, "dmfe_interrupt()", 0);
	outl(0, ioaddr + DCR7);
	db->cr5_data = inl(ioaddr + DCR5);
	outl(db->cr5_data, ioaddr + DCR5);
	if (db->cr5_data & 0x2000) {
		DMFE_DBUG(1, "A system bus error occurred. CR5=", db->cr5_data);
		netif_stop_queue(dev);
		db->wait_reset = 1;		
		outl(0, ioaddr + DCR7);		
		return;
	}
	txptr = db->tx_remove_ptr;
	while (db->tx_packet_cnt) {
		if (txptr->tdes0 & 0x80000000)
			break;
		db->stats.tx_packets++;
		if ((txptr->tdes0 & TDES0_ERR_MASK) && (txptr->tdes0 != 0x7fffffff)) {
			db->stats.tx_errors++;
		}
		if (txptr->tdes0 != 0x7fffffff) {
 			db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
			db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
			if (txptr->tdes0 & TDES0_ERR_MASK)
				db->stats.tx_errors++;
		}
		txptr = (struct tx_desc *) txptr->next_tx_desc;
		db->tx_packet_cnt--;
	}
	db->tx_remove_ptr = (struct tx_desc *) txptr;
	if ((db->tx_packet_cnt < TX_MAX_SEND_CNT) && db->tx_queue_cnt) {
		txptr->tdes0 = 0x80000000;	
		db->tx_packet_cnt++;	
		outl(0x1, ioaddr + DCR1);	
		dev->trans_start = jiffies;	
		db->tx_queue_cnt--;
 	}
	if (db->tx_packet_cnt < TX_FREE_DESC_CNT)
		netif_wake_queue(dev);
	if (db->rx_avail_cnt)
		dmfe_rx_packet(dev, db);
	if (db->rx_avail_cnt < RX_DESC_CNT)
		allocated_rx_buffer(db);
	if (db->dm910x_chk_mode & 0x2) {
		db->dm910x_chk_mode = 0x4;
		db->cr6_data |= 0x100;
		update_cr6(db->cr6_data, db->ioaddr);
	}
	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
		db->cr7_data = 0x1a28d;
	else
		db->cr7_data = 0x1a2cd;
	outl(db->cr7_data, ioaddr + DCR7);
}
static void dmfe_interrupt ( int irq , void * dev_id , struct pt_regs * regs ) { struct net_device * dev = dev_id ; struct tx_desc * txptr ; struct dmfe_board_info * db ; u32 ioaddr ; if ( ! dev ) { DMFE_DBUG ( 1 , " " , 0 ) ; return ; } db = ( struct dmfe_board_info * ) dev -> priv ; ioaddr = dev -> base_addr ; DMFE_DBUG ( 0 , " " , 0 ) ; outl ( 0 , ioaddr + DCR7 ) ; db -> cr5_data = inl ( ioaddr + DCR5 ) ; outl ( db -> cr5_data , ioaddr + DCR5 ) ; if ( db -> cr5_data & 0x2000 ) { DMFE_DBUG ( 1 , " " , db -> cr5_data ) ; netif_stop_queue ( dev ) ; db -> wait_reset = 1 ; outl ( 0 , ioaddr + DCR7 ) ; return ; } txptr = db -> tx_remove_ptr ; while ( db -> tx_packet_cnt ) { if ( txptr -> tdes0 & 0x80000000 ) break ; db -> stats . tx_packets ++ ; if ( ( txptr -> tdes0 & TDES0_ERR_MASK ) && ( txptr -> tdes0 != 0x7fffffff ) ) { db -> stats . tx_errors ++ ; } if ( txptr -> tdes0 != 0x7fffffff ) { db -> stats . collisions += ( txptr -> tdes0 >> 3 ) & 0xf ; db -> stats . tx_bytes += txptr -> tdes1 & 0x7ff ; if ( txptr -> tdes0 & TDES0_ERR_MASK ) db -> stats . tx_errors ++ ; } txptr = ( struct tx_desc * ) txptr -> next_tx_desc ; db -> tx_packet_cnt -- ; } db -> tx_remove_ptr = ( struct tx_desc * ) txptr ; if ( ( db -> tx_packet_cnt < TX_MAX_SEND_CNT ) && db -> tx_queue_cnt ) { txptr -> tdes0 = 0x80000000 ; db -> tx_packet_cnt ++ ; outl ( 0x1 , ioaddr + DCR1 ) ; dev -> trans_start = jiffies ; db -> tx_queue_cnt -- ; } if ( db -> tx_packet_cnt < TX_FREE_DESC_CNT ) netif_wake_queue ( dev ) ; if ( db -> rx_avail_cnt ) dmfe_rx_packet ( dev , db ) ; if ( db -> rx_avail_cnt < RX_DESC_CNT ) allocated_rx_buffer ( db ) ; if ( db -> dm910x_chk_mode & 0x2 ) { db -> dm910x_chk_mode = 0x4 ; db -> cr6_data |= 0x100 ; update_cr6 ( db -> cr6_data , db -> ioaddr ) ; } if ( db -> interval_rx_cnt > RX_MAX_TRAFFIC ) db -> cr7_data = 0x1a28d ; else db -> cr7_data = 0x1a2cd ; outl ( db -> cr7_data , ioaddr + DCR7 ) ; }
DM9102 insterrupt handler
receive the packet to upper layer, free the transmitted packet
DM9102 insterrupt handler receive the packet to upper layer free the transmitted packet
/* A real interrupt coming */ /* Disable all interrupt in CR7 to solve the interrupt edge problem */ /* Got DM910X status */ /* printk("CR5=%x\n", db->cr5_data); */ /* Check system status */ /* A system bus error occurred */ /* Need to RESET */ /* disable all interrupt */ /* Free the transmitted descriptor */ /* printk("tdes0=%x\n", txptr->tdes0); */ /* printk("tdes0=%x\n", txptr->tdes0); */ /* Transmit statistic counter */ /* printk("tdes0=%x\n", txptr->tdes0); */ /* Update TX remove pointer to next */ /* Send the Tx packet in queue */ /* set owner bit to DM910X */ /* Ready to send count */ /* Issue Tx polling command */ /* saved the time stamp */ /* Resource available check */ /* Received the coming packet */ /* reallocated rx descriptor buffer */ /* Mode Check */ /* Restore CR7 to enable interrupt mask */