⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm9000x.c

📁 uclinux下 dm9000x 网卡芯片 成熟驱动!
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif
	    }			// end of switch
        }				// end of if
    }
    
//edit by fae
#if 1
    phy_write(db, 0, 0x8000);	
    phy_write(db, 4, phy_reg4);
    phy_write(db, 0, phy_reg0);
#else    
    phy_write(db, 0, phy_reg0);
    phy_write(db, 4, phy_reg4);
#endif    
    
   /* 
	for(i = 0; i < 30000; i++)
	{
	  udelay (1000); 
	  if(ior(db, 0x01) & 0x40) break;
	}
	
	printk("link:%s , speed:%s , duplex:%s \n",
	        (ior (db, 0x01) & 0x40) ? "ok": "fail",
	        (ior (db, 0x01) & 0x80) ? "10Mbps": "100Mbps",
	        (ior (db, 0x00 ) & 0x08) ? "Full": "Half");
	*/
    db->Preg0 = phy_reg0;
    db->Preg4 = phy_reg4;
}


/* Initilize dm9000 board */
static void dmfe_init_dm9000(struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;

    DMFE_DBUG(0, "dmfe_init_dm9000()", 0);

//edit by fae
#if 0
    /* set the internal PHY power-on, GPIOs normal, and wait 2ms */
	iow(db, 0x1F, 1);		/* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY  */
	udelay(500);
    iow(db, 0x1F, 0);		/* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY  */
    if(ETH_DM9008AE == board_nic) //DM9008
    {
	udelay(200);
	
        /* set the internal PHY power-on, GPIOs normal, and wait 2ms */
	iow(db, 0x1F, 1);		/* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY  */
	udelay(700);
       iow(db, 0x1F, 0);		/* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY  */
    }	
#endif
	    
    udelay(20);	
    /* do a software reset and wait 20us */
    iow(db, DM9000_NCR, 3);
    udelay(20);			/* wait 20us at least for software reset ok */
    iow(db, DM9000_NCR, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
    udelay(20);			/* wait 20us at least for software reset ok */

	
    /* I/O mode */
    db->io_mode = ior(db, 0xfe) >> 6;	/* ISR bit7:6 keeps I/O mode */

//edit by fae
#if 1
    /* set the internal PHY power-on, GPIOs normal, and wait 2ms */
	iow(db, 0x1F, 1);		/* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY  */
	udelay(500);
    iow(db, 0x1F, 0);		/* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY  */
    
	/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
	iow(db, 0x1F, 1);		/* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY  */
	
    /* Set PHY */
    db->op_mode = media_mode;
    set_PHY_mode(db);
	
	udelay(700);
    iow(db, 0x1F, 0);		/* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY  */
#else
    /* Set PHY */
    db->op_mode = media_mode;
    set_PHY_mode(db);
#endif

    /* Init needed register value */
    db->reg0 = DM9000_NCR;

    /* User passed argument */
    db->reg5 = reg5;
    db->reg8 = reg8;
    db->reg9 = reg9;
    db->rega = rega;

    /* Program operating register */
    iow(db, 0x00, 0);
    iow(db, 0x02, 0);		/* TX Polling clear */
    iow(db, 0x2d, 0x80);
    iow(db, 0x08, 0x3f);	/* Less 3kb, 600us */
    iow(db, 0x2f, 0);		/* Special Mode */
    iow(db, 0x01, 0x2c);	/* clear TX status */
    iow(db, 0xfe, 0x0f); 	/* Clear interrupt status */
    if(ETH_DM9008AE == board_nic) //DM9008
    {
        iow(db, 0x8, 0x37);
        iow(db, 0x9, 0x38);
        iow(db, 0xa, 0x28);
    }
    /* Set address filter table */
    dm9000_hash_table(dev);

//edit by fae
#if 1
	iow(db, 0x38, 0x21);
	iow(db, 0x30, 0x81);
    iow(db, 0xa, 0x28);
//    iow(db, 0x39, 0x01);
	iow(db, 0x32, 0x02);
	
	db->rx_int_timer = 0;
#endif
	
    /* Activate DM9000 */
    iow(db, 0x05, db->reg5 | 1);	/* RX enable */
    iow(db, 0xff, DM9000_REGFF);	/* Enable TX/RX interrupt mask */

    /* Init Driver variable */
    db->link_failed	= 0;
    db->tx_pkt_cnt	= 0;
    db->queue_pkt_len	= 0;
    dev->trans_start	= 0;

    netif_carrier_on(dev);
    spin_lock_init(&db->lock);
    if(db->ioaddr==0x20300000)
       	   {
                *pFIO_FLAG_C   =  WAN_FIO_PATTERN;
       	  *pFIO_INEN    |=  WAN_FIO_PATTERN;          
       	    }
   
    if(db->ioaddr==0x20300010)
	
                 {                                                                
                 *pFIO_FLAG_C   =  LAN_FIO_PATTERN;        
                 *pFIO_INEN    |=  LAN_FIO_PATTERN;           
                  }
}

//edit by fae 05/08
#if 1
/* reset dm9000 board */
static void dmfe_reset_dm9000(struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;

    DMFE_DBUG(0, "dmfe_reset_dm9000()", 0);
    printk("\ndmfe_reset_dm9000()\n");

    udelay(20);	
    /* do a software reset and wait 20us */
    iow(db, DM9000_NCR, 3);
    udelay(20);			/* wait 20us at least for software reset ok */
    iow(db, DM9000_NCR, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
    udelay(20);			/* wait 20us at least for software reset ok */

    /* Init needed register value */
    db->reg0 = DM9000_NCR;

    /* User passed argument */
    db->reg5 = reg5;
    db->reg8 = reg8;
    db->reg9 = reg9;
    db->rega = rega;

    /* Program operating register */
    iow(db, 0x00, 0);
    iow(db, 0x02, 0);		/* TX Polling clear */
    iow(db, 0x2d, 0x80);
    iow(db, 0x08, 0x3f);	/* Less 3kb, 600us */
    iow(db, 0x2f, 0);		/* Special Mode */
    iow(db, 0x01, 0x2c);	/* clear TX status */
    iow(db, 0xfe, 0x0f); 	/* Clear interrupt status */
    if(ETH_DM9008AE == board_nic) //DM9008
    {
        iow(db, 0x8, 0x37);
        iow(db, 0x9, 0x38);
        iow(db, 0xa, 0x28);
    }

//edit by fae
#if 1
	iow(db, 0x38, 0x21);
	iow(db, 0x30, 0x81);
    iow(db, 0xa, 0x28);
//    iow(db, 0x39, 0x01);
	iow(db, 0x32, 0x02);
	
	db->rx_int_timer = 0;
#endif

    /* Activate DM9000 */
    iow(db, 0x05, db->reg5 | 1);	/* RX enable */
    iow(db, 0xff, DM9000_REGFF);	/* Enable TX/RX interrupt mask */

    /* Init Driver variable */
    db->link_failed	= 0;
    db->tx_pkt_cnt	= 0;
    db->queue_pkt_len	= 0;
    dev->trans_start	= 0;

    netif_carrier_on(dev);
    spin_lock_init(&db->lock);
    if(db->ioaddr==0x20300000)
       	   {
                *pFIO_FLAG_C   =  WAN_FIO_PATTERN;
       	  *pFIO_INEN    |=  WAN_FIO_PATTERN;          
       	    }
   
    if(db->ioaddr==0x20300010)
	
                 {                                                                
                 *pFIO_FLAG_C   =  LAN_FIO_PATTERN;        
                 *pFIO_INEN    |=  LAN_FIO_PATTERN;           
                  }
}
#endif


/* Hardware start transmission.
 * Send a packet to media from the upper layer.
 */
static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;
    char *data_ptr;
    int i, tmplen;

    DMFE_DBUG(0, "dmfe_start_xmit", 0);

//edit by fae
#if 1
	if(db->tx_pkt_cnt) return 1;
//	if(ior(db, 0x02) & 0x01) return 1;
//	ior(db, 0x30);
//	if(ior(db, 0x30) & 0x60) return 1;
#else
    if (db->tx_pkt_cnt >= 1) return 1;
#endif

    netif_stop_queue(dev);

    /* Disable all interrupt */
    iow(db, 0xff, 0x80);

//edit by fae
#if 1
	/* Set TX length to DM9000 */
	iow(db, 0xfc, skb->len & 0xff);
	iow(db, 0xfd, (skb->len >> 8) & 0xff);
#endif


    /* Move data to DM9000 TX RAM */
    data_ptr = (char *) skb->data;
    outb(0xf8, db->ioaddr);

    db->sent_pkt_len = skb->len;

    if (db->io_mode == DM9000_BYTE_MODE) {	    /* Byte mode */
	for (i = 0; i < skb->len; i++)
	    outb((data_ptr[i] & 0xff), db->io_data);
    } else if (db->io_mode == DM9000_WORD_MODE) {   /* Word mode */
	tmplen = (skb->len + 1) / 2;
	for (i = 0; i < tmplen; i++)
	    outw(((u16 *) data_ptr)[i], db->io_data);
    } else {					    /* DWord mode */
	tmplen = (skb->len + 3) / 4;
	for (i = 0; i < tmplen; i++)
	    outl(((u32 *) data_ptr)[i], db->io_data);
    }

//edit by fae
#if 1
	db->tx_pkt_cnt++;
	
//	iow(db, 0x2, 0x1);			/* Cleared after TX complete */	
	
	/* saved the time stamp */
	dev->trans_start = jiffies;
	
    /* free this SKB */
    dev_kfree_skb(skb);
	
#else
    /* TX control: First packet immediately send, second packet queue */
    if (db->tx_pkt_cnt == 0) {			/* First Packet */
	db->tx_pkt_cnt++;

	/* Set TX length to DM9000 */
	iow(db, 0xfc, skb->len & 0xff);
	iow(db, 0xfd, (skb->len >> 8) & 0xff);

	/* Issue TX polling command */
	iow(db, 0x2, 0x1);			/* Cleared after TX complete */
	
	/* saved the time stamp */
	dev->trans_start = jiffies;
    } else {					/* Second packet */
	db->tx_pkt_cnt++;
	db->queue_pkt_len = skb->len;
    }
	
    /* free this SKB */
    dev_kfree_skb(skb);

    /* Re-enable resource check */
    if (db->tx_pkt_cnt == 1) netif_wake_queue(dev);
#endif    

    /* Re-enable interrupt */
    iow(db, 0xff, 0x83);

    return 0;
}

/* Stop the interface.
 * The interface is stopped when it is brought.
 */
static int dmfe_stop(struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;

    DMFE_DBUG(0, "dmfe_stop", 0);

    /* deleted timer */
    del_timer(&db->timer);

    netif_stop_queue(dev);

    /* free interrupt */
    free_irq(dev->irq, dev);

    /* RESET devie */
    phy_write(db, 0x00, 0x8000);	/* PHY RESET */
    iow(db, 0x1f, 0x01);	/* Power-Down PHY */
    iow(db, 0xff, 0x80);	/* Disable all interrupt */
    iow(db, 0x05, 0x00);	/* Disable RX */


#if FALSE /* Dump Statistic counter */
    printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors);
    printk("RX CRC %lx\n", db->stats.rx_crc_errors);
    printk("RX LEN Err %lx\n", db->stats.rx_length_errors);
    printk("RX LEN < 64byte %x\n", db->runt_length_counter);
    printk("RX LEN > 1514byte %x\n", db->long_length_counter);
    printk("RESET %x\n", db->reset_counter);
    printk("RESET: TX Timeout %x\n", db->reset_tx_timeout);
    printk("RESET: RX Status Wrong %x\n", db->reset_rx_status);
#endif

    return 0;
}

static void dmfe_tx_done(struct net_device *dev_ptr)
{
    struct net_device *dev = dev_ptr;
    board_info_t *db = (board_info_t *) dev->priv;
    int tx_status = ior(db, 0x01);	/* Got TX status */
	
    DMFE_DBUG(0, "dmfe_tx_done()", 0);
//edit by fae
#if 1
//	if(!(ior(db, 0x02) & 0x01))
//	ior(db, 0x30);
//	if(!(ior(db, 0x30) & 0x60))
	{
		db->tx_pkt_cnt--;
		dev->trans_start = 0;
		db->stats.tx_packets++;
		netif_wake_queue(dev);
	}
#else    
    if (tx_status & 0xc) {		/* One packet sent complete */
	db->tx_pkt_cnt--;
	dev->trans_start = 0;
	db->stats.tx_packets++;

	if (db->tx_pkt_cnt > 0) {	/* Queue packet check & send */
	    /* Set TX length to DM9000 */
	    iow(db, 0xfc, db->queue_pkt_len & 0xff);
	    iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff);

	    /* Issue TX polling command */
	    iow(db, 0x2, 0x1);		/* Cleared after TX complete */
	    dev->trans_start = jiffies;	/* saved the time stamp */
	}
	netif_wake_queue(dev);
    }
#endif
}

/* DM9102 insterrupt handler.
 * receive the packet to upper layer, free the transmitted packet
 */
static int dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    struct net_device *dev = dev_id;
    board_info_t *db;
    int int_status;
    u8 reg_save;
    unsigned long flags;

#if 0	/* comment by mhfan */
    DMFE_DBUG(0, "dmfe_interrupt()", 0);
#else	
	/*
    if (!(*pFIO_FLAG_C & LAN_FIO_PATTERN)) return IRQ_NONE;
    *pFIO_FLAG_C = LAN_FIO_PATTERN;
    asm __volatile__ ("ssync;");
	*/
#endif	/* comment by mhfan */

    if (!dev) 
    {
	DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);
	return IRQ_NONE;
    }

    tintrflag++;
    /* A real interrupt coming */
    db = (board_info_t *) dev->priv;
#if 1 	/* comment by mhfan */
    spin_lock(&db->lock); 
#else
    spin_lock_irqsave(&db->lock,flags);
	/*local_irq_save(flags); *//* comment by guang */
#endif	/* comment by mhfan */

    /* Save previous register address */
    reg_save = inb(db->ioaddr);

    /* Disable all interrupt */
    //iow(db, 0xff, 0x80);

    /* Got DM9000 interrupt status */
    int_status = ior(db, 0xfe);	/* Got ISR */
    
//edit by fae
#if 1
    iow(db, 0xfe, int_status & 0xfc);	/* Clear ISR status */
#else
    iow(db, 0xfe, int_status);	/* Clear ISR status */
#endif
    /* clear irq status on interrupt lines 
    Add by Zhoujh ,2006.10.30       */
    if(DM9000_ETH0_IO == db->ioaddr)
    {
	*pFIO_FLAG_C = WAN_FIO_PATTERN; 
    }
    else
    {
	*pFIO_FLAG_C = LAN_FIO_PATTERN; 
    }

    if (int_status & DM9000_LNKCHG_INTR)
    {
		/*		
		printk("link change:%s , speed:%s , duplex:%s \n",
	        (ior (db, 0x01) & 0x40) ? "ok": "fail",
	        (ior (db, 0x01) & 0x80) ? "10Mbps": "100Mbps",
	        (ior (db, 0x00 ) & 0x08) ? "Full": "Half");
		*/
    }

//edit by fae
#if 0
    if (int_status & DM9000_TX_INTR) 
    {	/* Trnasmit Interrupt check */
	//printk("%s TX\n",dev->name);
	dmfe_tx_done(dev);
    }
#endif    

    if (int_status & DM9000_RX_INTR) 
    {		/* Received the coming packet */
       /*printk("%s RX\n",dev->name);*/
//edit by fae
#if 1
	db->rx_int_timer = jiffies;
	/*printk("%s RX\n",dev->name);*/
	rxintrflag++;
	dmfe_packet_receive(dev);
	iow(db, 0xfe, DM9000_RX_INTR);
#else
       /*printk("%s RX\n",dev->name);*/
	rxintrflag++;
	dmfe_tx_done(dev);		/* perhaps it is a bug for chip */
	dmfe_packet_receive(dev);
#endif
    }

//edit by fae
#if 1
	int_status |= ior(db, 0xfe);	/* Got ISR */
	
    if (int_status & DM9000_TX_INTR) 
    {	/* Trnasmit Interrupt check */
	//printk("%s TX\n",dev->name);
	dmfe_tx_done(dev);
	
	iow(db, 0xfe, DM9000_TX_INTR);
    }
#endif

    /* Re-enable interrupt mask */
   // iow(db, 0xff, 0x83);

    /* Restore previous register address */
    outb(reg_save, db->ioaddr);

    spin_unlock(&db->lock);
    //spin_unlock_irqrestore(&db->lock,flags);

    return IRQ_HANDLED;
}

/*
  Get statistics from driver.
*/
static struct net_device_stats *dmfe_get_stats(struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;

    DMFE_DBUG(0, "dmfe_get_stats", 0);
    return &db->stats;
}

/*
  Process the upper socket ioctl command
*/
static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
    DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
    return 0;
}

/*
  A periodic timer routine
  Dynamic media sense, allocated Rx buffer...
*/
static void dmfe_timer(unsigned long data)
{
    struct net_device *dev = (struct net_device *) data;
    board_info_t *db = (board_info_t *) dev->priv;
    u8 reg_save, tmp_reg;

//edit by fae

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -