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

📄 dm9000x.c

📁 一个嵌入linux下s3c2410通过i2c读写eerom的驱动程序和应用程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 dev_num){	struct net_device *dev = NULL;	board_info_t *db = NULL ;	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);		if ( dev_num == 0 )		dev = dmfe_eth0_dev ;	else if ( dev_num == 1 )		dev = dmfe_eth1_dev ;	     else 		return ;					db = (board_info_t *)dev->priv;		/* 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(dev);		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);	}}/* The little-endian AUTODIN II ethernet CRC calculation.   N.B. Do not use for bulk data, use a table-based routine instead.   This is common code and should be moved to net/core/crc.c */static unsigned const ethernet_polynomial_le = 0xedb88320U;static inline unsigned ether_crc_le(int length, unsigned char *data){	unsigned int crc = 0xffffffff;	/* Initial value. */	while(--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 8; --bit >= 0; current_octet >>= 1) {			if ((crc ^ current_octet) & 1) {				crc >>= 1;				crc ^= ethernet_polynomial_le;			} else				crc >>= 1;		}	}	return crc;}/*  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(eth0_mac_string,"s");MODULE_PARM(eth1_mac_string,"s");//MODULE_PARM(SF_mode, "i");/* *  convert an ascii hex char digit to a number. *  param is hex digit. *  returns a decimal digit. */static int hex_char2digit (char digit){	if (digit == 0)		return 0;	if (digit >= '0' && digit <= '9')		return digit - '0';	if (digit >= 'a' && digit <= 'f')		return digit - 'a' + 10;	if (digit >= 'A' && digit <= 'F')		return digit - 'A' + 10;	/* shouldn't ever get this far */	return -1;}static int hex_string2int (char *hex_ptr){	int hexValue;	int ret = 0;	while (*hex_ptr)	{		hexValue = hex_char2digit(*hex_ptr);		if (hexValue < 0)			return -1;		ret = (ret << 4) | hexValue;		hex_ptr++;	}	return ret;}static char *strdup(char *str){ 	int n = strlen(str)+1; 	char *s = kmalloc(n, GFP_KERNEL); 	if (!s) return NULL; 	return strcpy(s, str);}/* Description:    when user used insmod to add module, system invoked init_module()   to initilize and register.*/int init_module(void){	int cnt;	char *ptr;		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;	ptr = strdup(eth0_mac_string);	cnt = 0 ;	while (cnt < 6 )	{		char *tail;				if ( *ptr == '\0' )			break;		if ( *ptr != ' ' )		{			tail = ptr;			while ( *tail != ' ' && *tail != '\0' )				tail++;			*tail = '\0' ;			eth0_mac_addr[cnt] = hex_string2int(ptr);			cnt++;			ptr = tail+1;		} else 			ptr++;	}	kfree(ptr);		ptr = strdup(eth1_mac_string);	cnt = 0 ;	while (cnt < 6 )	{		char *tail;				if ( *ptr == '\0')			break;		if ( *ptr != ' ')		{			tail = ptr;			while ( *tail != ' ' && *tail != '\0' )				tail++;			*tail = '\0' ;			eth1_mac_addr[cnt] = hex_string2int(ptr);			cnt++;			ptr = tail+1;		} else 			ptr++;	}	kfree(ptr);	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);	if ( dmfe_eth0_dev ) 	{		db = (board_info_t *)dmfe_eth0_dev->priv;		iounmap((void*)db->ioaddr);		release_region(dmfe_eth0_dev->base_addr, 2);		kfree(db);		/* free board information */		kfree(dmfe_eth0_dev);	/* free device structure */		unregister_netdev(dmfe_eth0_dev);	}	if ( dmfe_eth1_dev )	{		db = (board_info_t *)dmfe_eth1_dev->priv;		iounmap((void*)db->ioaddr);		release_region(dmfe_eth1_dev->base_addr, 2);		kfree(db);		/* free board information */		kfree(dmfe_eth1_dev);	/* free device structure */		unregister_netdev(dmfe_eth1_dev);	}	DMFE_DBUG(0, "clean_module() exit", 0);}#endif  /* MODULE */

⌨️ 快捷键说明

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