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

📄 dm9000x.c

📁 网卡芯片dm9000的驱动程序源码,该芯片为10M/100M以太网物理层芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  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;	//u8 tmpreg;		DMFE_DBUG(0, "dmfe_timer()", 0);	/* Save previous register address */	reg_save = inb(db->ioaddr);	/* TX timeout check */	if (dev->trans_start&&((jiffies-dev->trans_start)>DMFE_TX_TIMEOUT)) {		//printk("TX timeout reset.\n");		db->device_wait_reset = 1;		db->reset_tx_timeout++;	} 	/* 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;		dmfe_init_dm9000(dev);		netif_wake_queue(dev);	}	/* 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);			//printk(KERN_ERR "not link\n");		}	}	/* Restore previous register address */	outb(reg_save, db->ioaddr);	/* Set timer again */	db->timer.expires = DMFE_TIMER_WUT;	add_timer(&db->timer);}#if defined(AUTOMDIX)static void dmfe_mdix_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	board_info_t *db = (board_info_t *)dev->priv;	/* support AUTO-MDIX */	db->mdix = ior(db, DM9000_GPR); 			db->link_status = ior(db, DM9000_NSR); 	db->link_status = test_bit(6, &db->link_status);	udelay(2000);	if (!db->link_status)	{		switch(db->mdix)		{		case 0x7c: //use parallel line change to cross line			if(netif_carrier_ok(dev))				netif_carrier_off(dev);			iow(db, DM9000_GPCR, 0x03);			iow(db, DM9000_GPR, 0x02);			break;		case 0x7e: // use cross line change to parallel line			if(netif_carrier_ok(dev))				netif_carrier_off(dev);			iow(db, DM9000_GPCR, 0x03);			iow(db, DM9000_GPR, 0x00);			break;		default:			break;		}	}	else{				 if (!netif_carrier_ok(dev)) 			netif_carrier_on(dev);	}		/* Set timer again */	db->mdix_timer.expires = DMFE_TIMER_MDIX;	add_timer(&db->mdix_timer);}#endif/*  Received a packet and pass to upper layer*/static void dmfe_packet_receive(unsigned long unused){	struct net_device *dev = dmfe_dev;	board_info_t *db = (board_info_t *)dev->priv;	struct sk_buff *skb;	u8 rxbyte, *rdptr;	u16 i, RxStatus, RxLen, GoodPacket, tmplen;//#ifndef EMU32	u32 tmpdata;//#endif 	DMFE_DBUG(0, "dmfe_packet_receive()", 0);	/* Check packet ready or not */	do {		ior(db, 0xf0);			/* Dummy read */		rxbyte = inb(db->io_data);	/* Got most updated data */		/* packet ready to receive check */		if (rxbyte == DM9000_PKT_RDY) 		{		    /* A packet ready now  & Get status/length */		    GoodPacket = TRUE;		    outb(0xf2, db->ioaddr);		    /* Selecting io mode */					RxStatus = (u16)0;			RxLen    = (u16)0;			/* modify Select io mode by jackal 10/28/2003 */			switch (db->io_mode) 			{			  case DM9000_BYTE_MODE:  				    RxStatus = inb(db->io_data) + 				               (inb(db->io_data) << 8);				    RxLen = inb(db->io_data) + 					    (inb(db->io_data) << 8);				    break;			  case DM9000_WORD_MODE:				    RxStatus = inw(db->io_data);				    RxLen    = inw(db->io_data);				    break;			  case DM9000_DWORD_MODE://#if defined(EMU32)//				    // Emulate 32bits mode on ISA of pc//				    RxStatus = inw(db->io_data);//				    RxLen    = inw(0x320);//#else				    tmpdata  = inl(db->io_data);				    RxStatus = tmpdata;				    RxLen    = tmpdata >> 16;//#endif				    break;			  default:				    break;			}			/* Packet Status check */			if (RxLen < 0x40) 			{ 			    GoodPacket = FALSE; 			    db->runt_length_counter++; 			} else if (RxLen > DM9000_PKT_MAX) 			       { 			 	    //printk("<DM9000> RST: RX Len:%x\n", RxLen);				    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++;			}			/* Move data from DM9000 */			if (!db->device_wait_reset) {				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 */					if (db->io_mode == DM9000_BYTE_MODE) {						/* Byte mode */						for (i=0; i<RxLen; i++)							rdptr[i]=inb(db->io_data);					} else if (db->io_mode == DM9000_WORD_MODE) {						/* Word mode */						tmplen = (RxLen + 1) / 2;						for (i = 0; i < tmplen; i++)							((u16 *)rdptr)[i] = inw(db->io_data);					} else {						/* DWord mode *///#if defined(EMU32)//						//Emulate 32bits mode on ISA of PC//						tmplen = (RxLen + 3) / 4;//						for (i = 0; i < tmplen; i++)//						{//							((u16 *)rdptr)[i*2] = inw(db->io_data);//							((u16 *)rdptr)[i*2+1] = inw(0x320);							//						}//#else						tmplen = (RxLen + 3) / 4;						for (i = 0; i < tmplen; i++)							((u32 *)rdptr)[i] = inl(db->io_data);//#endif											} 										/* Pass to upper layer */					skb->protocol = eth_type_trans(skb,dev);					netif_rx(skb);					db->stats.rx_packets++; 									} else {					/* Without buffer or error packet */					if (db->io_mode == DM9000_BYTE_MODE) {						/* Byte mode */						for (i = 0; i < RxLen; i++)							inb(db->io_data);					} else if (db->io_mode == DM9000_WORD_MODE) {						/* Word mode */						tmplen = (RxLen + 1) / 2;						for (i = 0; i < tmplen; i++)							inw(db->io_data);					} else {						/* DWord mode *///#if defined(EMU32)//						//Emulate 32 bits mode on ISA of PC	//						tmplen = (RxLen + 3) / 4;//						for (i = 0; i < tmplen; i++)//						{//							inw(db->io_data);//							inw(0x320);							//						}//#else						tmplen = (RxLen + 3) / 4;						for (i = 0; i < tmplen; i++)							inl(db->io_data);//#endif																	} 				}			}		}		/* Status check: this byte must be 0 or 1 */		else if (rxbyte > DM9000_PKT_RDY) {//			printk("RX SRAM 1st byte != 01, must reset.\n");			iow(db, 0x05, 0x00);	/* Stop Device */			iow(db, 0xfe, 0x80);	/* Stop INT request */			db->device_wait_reset = TRUE;			db->reset_rx_status++;		}	}while(rxbyte == DM9000_PKT_RDY && !db->device_wait_reset);//*Spenser	if (!db->device_wait_reset)	{		dmfe_tx_done(0);		iow(db, 0xff, 0x83);	}}/*  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) );}/*  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 MODULEMODULE_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;	}#if 0	/* added by jackal for SF_mode */	switch(SF_mode)	{		case VLAN_Enable:		case FlowControl:		case TxPausePacket:			sf_mode = SF_mode;			break;		default:			sf_mode = 0;			break;	}#endif 	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){	board_info_t * db;	DMFE_DBUG(0, "clean_module()", 0);	unregister_netdev(dmfe_dev);	db = (board_info_t *)dmfe_dev->priv;	release_region(dmfe_dev->base_addr, 2);#ifdef CONFIG_ARCH_EV2440		iounmap((void *)(dmfe_dev->base_addr&~0x3ff));#endif	kfree(db);		/* free board information */	kfree(dmfe_dev);	/* free device structure */		DMFE_DBUG(0, "clean_module() exit", 0);}#endif  /* MODULE */

⌨️ 快捷键说明

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