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

📄 dm9000x.c

📁 uclinux下 dm9000x 网卡芯片 成熟驱动!
💻 C
📖 第 1 页 / 共 3 页
字号:
#if 1
	/* Save previous register address */
    reg_save = inb(db->ioaddr);
#endif

/*printk("%s RX\n",dev->name);*/
    if(ETH_DM9008AE == board_nic) //DM9008
    {
        if(ior(db, 0x01) & 0x40)
    	    db->link_failed = 1;
        else
        {
            /* 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  */
	    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  */
	    udelay(20);
    	    db->link_failed = 0;
        }
    }
//      DMFE_DBUG(0, "dmfe_timer()", 0);

//edit by fae
#if 0
	/* Save previous register address */
    reg_save = inb(db->ioaddr);
#endif

    /* TX timeout check */
    if (dev->trans_start && ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) {
	db->device_wait_reset = 1;
	db->reset_tx_timeout++;
    }
    
//edit by fae
#if 1
    /* RX timeout check */
    if (db->rx_int_timer && ((jiffies - db->rx_int_timer) > (2 * HZ))) {
			db->device_wait_reset = 1;
			db->reset_tx_timeout++;
    }
#endif

    /* DM9000 dynamic RESET check and do */
    if (db->device_wait_reset) {
	netif_stop_queue(dev);
	db->reset_counter++;
	db->device_wait_reset = 0;
	dev->trans_start = 0;
//edit by fae
#if 1
	dmfe_reset_dm9000(dev);
#else	
	dmfe_init_dm9000(dev);
#endif
	netif_wake_queue(dev);
    }


//edit by fae
#if 0
    /* Auto Sense Media mode policy: FastEthernet NIC: don't need to do
     * anything. Media Force mode: don't need to do anything. HomeRun/LongRun 
     * NIC and AUTO_Mode: INT_MII not link, select EXT_MII EXT_MII not link,
     * select INT_MII */
    if ((db->nic_type != FASTETHER_NIC) & (db->op_mode == DM9000_AUTO)) {
	tmp_reg = ior(db, 0x01);	/* Got link status */
	if (!(tmp_reg & 0x40)) {	/* not link */
	    db->reg0 ^= 0x80;
	    iow(db, 0x00, db->reg0);
	}
    }
#endif

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

    /* Set timer again */
    db->timer.expires = DMFE_TIMER_WUT;
    add_timer(&db->timer);
}



/* Received a packet and pass to upper layer */
static void dmfe_packet_receive(struct net_device *dev_ptr)
{
	struct net_device *dev = dev_ptr;
	board_info_t *db = (board_info_t *) dev->priv;
	struct sk_buff *skb;
	u8 rxbyte, *rdptr;
	u16 i, RxStatus, RxLen, GoodPacket, tmplen;
	u32 tmpdata;
	
//edit by fae
#if 1
	u16 int_rx_cnt = 0;
#endif
	
	
	DMFE_DBUG(0, "dmfe_packet_receive()", 0);
	do {				/* Check packet ready or not */
		ior(db, 0xf0);			/* Dummy read */
//edit by fae
#if 1		
		ior(db, 0xfe);
		rxbyte = ior(db, 0xf0);
	
		switch(rxbyte)
		{
			case 0x00 : 
				return;
				break;
			case 0x01 :
				break;
			case 0x05 : // ip 
				break;
			case 0x0d : // tcp
				break;
			case 0x15 : // udp
				break;
//			
			case 0x25 :  // ip check sum err 
				break;
//
			case 0x2d : // ip , check sum err 
				break;
			case 0x4d : // tcp , check sum err
				break;
			case 0x6d : // ip , tcp check sum err
				break;
//			
			case 0x35 : // ip , echek sum err 
				break;
			case 0x95 : // udp , check sum err
				break;
			case 0xb5 : // ip , udp chekc sum err
				break;
			default :
				//printk("rx point error %02x \n", rxbyte);
				db->device_wait_reset = 1;
				return;
				break;
		}	
		
		if(db->device_wait_reset == 0x00)
#else
		rxbyte = inb(db->io_data);	/* Got most updated data */
		if (rxbyte == DM9000_PKT_RDY) 
#endif

		{ 	/* packet ready to receive check */
			/* A packet ready now & Get status/length */

//edit by fae
#if 1			
			db->rx_int_timer = 0;
#endif
			GoodPacket = TRUE;
			outb(0xf2, db->ioaddr);

			/* Selecting io mode */
			RxStatus = RxLen = (u16) 0;

			RxStatus = inw(db->io_data);

			RxLen = inw(db->io_data);


			/* Packet Status check */
			if (RxLen < 0x40) 
			{
				GoodPacket = FALSE;
				db->runt_length_counter++;
			} 
			else if (RxLen > DM9000_PKT_MAX) 
			{
				//printk("<DM9000> RST: RX Len:%x(%x)\n", RxLen, RxStatus);
				db->device_wait_reset = TRUE;
				db->long_length_counter++;
			}

			if (RxStatus & 0xbf00) 
			{
				GoodPacket = FALSE;
				if (RxStatus & 0x100)
					db->stats.rx_fifo_errors++;
				if (RxStatus & 0x200)
					db->stats.rx_crc_errors++;
				if (RxStatus & 0x8000)
					db->stats.rx_length_errors++;
			}

			if (!db->device_wait_reset) 
			{	
				/* Move data from DM9000 */
				if (GoodPacket && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) 
				{
					skb->dev = dev;
					skb_reserve(skb, 2);
					rdptr = (u8 *) skb_put(skb, RxLen - 4);
								
					/* Read received packet from RX SARM */
					/* Word mode */
					tmplen = (RxLen + 1) / 2;
					for (i = 0; i < tmplen; i++)
						((u16 *) rdptr)[i] = inw(db->io_data);
						
//edit by fae
#if 1	
		skb->ip_summed = CHECKSUM_UNNECESSARY;
		
		if((rxbyte == 0x01) || (rxbyte & 0xe0)) skb->ip_summed = CHECKSUM_NONE;
#endif
					/* Pass to upper layer */
					skb->protocol = eth_type_trans(skb, dev);
					netif_rx(skb);
					db->stats.rx_packets++;

				}	/* if (GoodPacket && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) */
				else 
				{	    
					/* Without buffer or error packet */
					/* Word mode */
					tmplen = (RxLen + 1) / 2;
					for (i = 0; i < tmplen; i++)
						inw(db->io_data);
					continue;/*next the packet*/
				}
			}
		} 

//edit by fae
#if 1
		if(db->device_wait_reset)
#else			
		else if (rxbyte > DM9000_PKT_RDY) 
#endif	
		{
			/* Status check: this byte must be 0 or 1 */
			printk("RX SRAM 1st byte(%02x) != 01, must reset.\n", rxbyte);
			iow(db, 0x05, 0x00);	/* Stop Device */
			iow(db, 0xfe, 0x00);	/* Stop INT request */
			db->device_wait_reset = TRUE;
			db->reset_rx_status++;
		}
		
//edit by fae
#if 1
		int_rx_cnt++;
		if(int_rx_cnt > MAX_RX_PACKET) return;
	} while (((rxbyte & 0x03) == DM9000_PKT_RDY) && (!db->device_wait_reset)); 
#else
	} while (rxbyte == DM9000_PKT_RDY && !db->device_wait_reset); 
#endif
}

#if 0	/* comment by mhfan */
/* Read a word data from SROM */
static u16 read_srom_word(board_info_t * db, int offset)
{
    iow(db, 0xc, offset);
    iow(db, 0xb, 0x4);
    udelay(200);
    iow(db, 0xb, 0x0);
    return (ior(db, 0xd) + (ior(db, 0xe) << 8));
}
#endif	/* comment by mhfan */

/* Set DM9000 multicast address */
static void dm9000_hash_table(struct net_device *dev)
{
    board_info_t *db = (board_info_t *) dev->priv;
    struct dev_mc_list *mcptr = dev->mc_list;
    int mc_cnt = dev->mc_count;
    u32 hash_val;
    u16 i, oft, hash_table[4];

    DMFE_DBUG(0, "dm9000_hash_table()", 0);

    /* Set Node address */
    for (i = 0, oft = 0x10; i < 6; i++, oft++)
	iow(db, oft, dev->dev_addr[i]);

    /* Clear Hash Table */
    for (i = 0; i < 4; i++) hash_table[i] = 0x0;

    /* broadcast address */
    hash_table[3] = 0x8000;

    /* the multicast address in Hash Table : 64 bits */
    for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
	hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
	hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
    }

    /* Write the hash table to MAC MD table */
    for (i = 0, oft = 0x16; i < 4; i++) {
	iow(db, oft++, hash_table[i] & 0xff);
	iow(db, oft++, (hash_table[i] >> 8) & 0xff);
    }
}

/* Calculate the CRC valude of the Rx packet
 * flag = 1 : return the reverse CRC (for the received packet CRC)
 *	  0 : return the  normal CRC (for Hash Table index)
 */
static unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
{

    u32 crc = ether_crc_le(Len, Data);

    if (flag) return ~crc;

    return crc;
}

/* Read a byte from I/O port */
static u8 ior(board_info_t * db, int reg)
{
    outb(reg, db->ioaddr);
    return inb(db->io_data);
}

/* Write a byte to I/O port */
static void iow(board_info_t * db, int reg, u8 value)
{
    outb(reg, db->ioaddr);
    outb(value, db->io_data);
}

/* Read a word from phyxcer */
static u16 phy_read(board_info_t * db, int reg)
{
    /* Fill the phyxcer register into REG_0C */
    iow(db, 0xc, DM9000_PHY | reg);

    iow(db, 0xb, 0xc);		/* Issue phyxcer read command */
    udelay(100);		/* Wait read complete */
    iow(db, 0xb, 0x0);		/* Clear phyxcer read command */

    /* The read data keeps on REG_0D & REG_0E */
    return (ior(db, 0xe) << 8) | ior(db, 0xd);
}

/* Write a word to phyxcer */
static void phy_write(board_info_t * db, int reg, u16 value)
{
    /* Fill the phyxcer register into REG_0C */
    iow(db, 0xc, DM9000_PHY | reg);

    /* Fill the written data into REG_0D & REG_0E */
    iow(db, 0xd, (value & 0xff));
    iow(db, 0xe, ((value >> 8) & 0xff));

    iow(db, 0xb, 0xa);		/* Issue phyxcer write command */
    udelay(500);		/* Wait write complete */
    iow(db, 0xb, 0x0);		/* Clear phyxcer write command */
}

#ifdef	MODULE
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
MODULE_DESCRIPTION("Davicom DM9000 ISA/uP Fast Ethernet Driver");
MODULE_PARM(debug, "i");
MODULE_PARM(mode, "i");
MODULE_PARM(reg5, "i");
MODULE_PARM(reg9, "i");
MODULE_PARM(rega, "i");
MODULE_PARM(nfloor, "i");
//MODULE_PARM(SF_mode, "i");

/* Description: 
 * when user used insmod to add module,
 * system invoked init_module() to initilize and register.
 */
int init_module(void)
{
    DMFE_DBUG(0, "init_module() ", debug);

    if (debug) dmfe_debug = debug;	/* set debug flag */

    switch (mode) {
    case DM9000_10MHD:
    case DM9000_100MHD:
    case DM9000_10MFD:
    case DM9000_100MFD:
    case DM9000_1M_HPNA:    media_mode = mode;	    break;
    default:		    media_mode = DM9000_AUTO;
    }
    nfloor = (nfloor > 15) ? 0 : nfloor;

    return dmfe_probe(0);	/* search board and register */
}

/* Description: 
 * when user used rmmod to delete module,
 * system invoked clean_module() to  un-register DEVICE.
 */
void cleanup_module(void)
{
    int i = 0;
    board_info_t *db;

    DMFE_DBUG(0, "clean_module()", 0);

    for(i = 0; i < 2; i++)
    {
        unregister_netdev(dmfe_dev[ i ]);
        db = (board_info_t *) dmfe_dev[ i ]->priv;
        release_region(dmfe_dev[ i ]->base_addr, 2);
        kfree(db);			/* free board information */
        kfree(dmfe_dev[ i ]);		/* free device structure */
    }
    DMFE_DBUG(0, "clean_module() exit", 0);
}
#else
static int get_dmfe_num(void)
{
	unsigned short gateway_type = 0 ;
	int dmfe_num = 1;

	gateway_type = *(volatile unsigned short *)GATEWAY_TYPE_ADDR;
	gateway_type = gateway_type&0x000f;
	switch(gateway_type)
	{
		case CNG100:dmfe_num = 1;
			break;
		case CNG100_2IF:dmfe_num = 2;
			break;
		default:dmfe_num = 1;
			break;
	}	
	return dmfe_num;
}

static unsigned short get_board_nic(void)
{
	unsigned short nic = 0, module = 0;
	nic = *( unsigned short *)NIC_TYPE_ADDR;
	module= *( unsigned short *)Module_type_addr;
	nic = nic&0x000f;
	module=module&0x000f;

	if(module==3)   /*当为1S1O的时候,CPLD里面对NIC的设置刚好是反的,这里软件统一*/
	{
		if(nic==0)     
			nic=1;
		else
			nic=0;
	}
	
	return nic;
}
/* Description: 
 * Modify by Zhoujh
 * for both single DM9008 and 2 DM9008
 */
static int __init dmfe_init_module(void)
{
    int err = -1,i = 0,dmfe_num = 0;

    board_nic = get_board_nic();
    dmfe_num = get_dmfe_num();
    FIO_PATTERN_INIT();
    if(2 == dmfe_num)
    {
#ifdef  CONFIG_BFIN
    __builtin_bfin_csync();
    *pFIO_MASKB_C  =  WAN_FIO_PATTERN;
    __builtin_bfin_ssync();
    __builtin_bfin_csync();
    *pFIO_MASKB_C  =  LAN_FIO_PATTERN;
    __builtin_bfin_ssync();
    *pFIO_POLAR   &= ~WAN_FIO_PATTERN;
    *pFIO_POLAR   &= ~LAN_FIO_PATTERN;
    *pFIO_EDGE    |= WAN_FIO_PATTERN;
    *pFIO_EDGE    |= LAN_FIO_PATTERN;
    *pFIO_BOTH    &= ~WAN_FIO_PATTERN;
    *pFIO_BOTH    &= ~LAN_FIO_PATTERN;
    *pFIO_DIR     &= ~WAN_FIO_PATTERN;
    *pFIO_DIR     &= ~LAN_FIO_PATTERN;
    //*pFIO_FLAG_C   =  WAN_FIO_PATTERN;  
    //*pFIO_FLAG_C   =  LAN_FIO_PATTERN;
    //*pFIO_INEN    |=  WAN_FIO_PATTERN;
    //*pFIO_INEN    |=  LAN_FIO_PATTERN;                       //enable it later!!!
        __builtin_bfin_ssync();
    *pFIO_MASKB_S  |=  WAN_FIO_PATTERN;
    __builtin_bfin_ssync();
    __builtin_bfin_ssync();
    *pFIO_MASKB_S  |=  LAN_FIO_PATTERN;
    __builtin_bfin_ssync();

    dmfe_dev[0] = alloc_etherdev(sizeof(*dmfe_dev[0]));      
    dmfe_dev[0]->init = dmfe_probe_eth0;                         
    dmfe_dev[1] = alloc_etherdev(sizeof(*dmfe_dev[1]));    
    dmfe_dev[1]->init = dmfe_probe_eth1;                         
#endif
    }
    else if(1 == dmfe_num)
    {
#ifdef	CONFIG_BFIN		
    __builtin_bfin_csync();    
    *pFIO_MASKB_C  =  WAN_FIO_PATTERN;	
    __builtin_bfin_ssync();	
    *pFIO_POLAR   &= ~WAN_FIO_PATTERN;    
    *pFIO_EDGE    |= WAN_FIO_PATTERN;	
    *pFIO_BOTH    &= ~WAN_FIO_PATTERN;	
    *pFIO_DIR     &= ~WAN_FIO_PATTERN;    
    *pFIO_FLAG_C   =  WAN_FIO_PATTERN;  
    *pFIO_INEN    |=  WAN_FIO_PATTERN;    	
    __builtin_bfin_ssync();	
    *pFIO_MASKB_S  =  WAN_FIO_PATTERN;	
    __builtin_bfin_ssync();	

    dmfe_dev[0] = alloc_etherdev(sizeof(*dmfe_dev[0]));                         
    dmfe_dev[0]->init = dmfe_probe_eth0;                               
#endif	/* comment by mhfan */    
   }

    for(i = 0; i < dmfe_num; i++)
    {
        /* Find a name for this unit */
        err = dev_alloc_name(dmfe_dev[i], "eth%d");
        if (err < 0) goto error_quit;
        err = register_netdev(dmfe_dev[i]);
        if (err < 0) goto error_quit; 
    }
return 0;
error_quit:	
return -1;
}

static void __exit dmfe_cleanup_module(void)
{
    int i = 0, dmfe_num;

    dmfe_num = get_dmfe_num();
    for(i = 0; i< dmfe_num;i++)
    {
        unregister_netdev(dmfe_dev[ i ]);
        kfree(dmfe_dev[ i ]->priv);

        memset(dmfe_dev[ i ], 0, sizeof (*dmfe_dev[ i ]));
        dmfe_dev[ i ]->init = dmfe_probe;
    }
}

module_init(dmfe_init_module);
module_exit(dmfe_cleanup_module);
#endif//MODULE

⌨️ 快捷键说明

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