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

📄 dm9000x.c

📁 S3C2410硬件平台下的UBOOT下的DM9000E驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Dump Statistic counter */#if 0	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}/*  DM9102 insterrupt handler  receive the packet to upper layer, free the transmitted packet*/static void dmfe_interrupt(int irq, void *dev_id){	DEVICE *dev = dev_id;	board_info_t *db;	unsigned long flags;	int int_status, tx_status;	u8 reg_save;	printf("*************** dmfe_interrupt()\n");	/* Clear interrupts for GPIO6 */	if (!dev) {		//printf("dmfe_interrupt() without DEVICE arg\n");		return;	}	//	*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_GPIOINTCLEAR)) = 0x00004040;//	save_and_cli(flags);	db = (board_info_t *)dev->priv;	/* 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 */	iow(db, 0xfe, int_status);		/* Clear ISR status *///	printf("Interrupt status = %x\n ", int_status);	/* Received the coming packet */	if (int_status & 1)		dmfe_packet_receive(dev);	/* Trnasmit Interrupt check */	if (int_status & 2) {		tx_status = ior(db, 0x01);	/* Got TX status *///		if (tx_status & 0xc) {  			/* One packet sent complete */			db->tx_pkt_cnt--;//			dev->trans_start = 0;//			db->stats.tx_packets++;			/* Queue packet check & send */			if (db->tx_pkt_cnt > 0) {				iow(db, 0xfc, db->queue_pkt_len & 0xff);				iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff);				iow(db, 0x2, 0x1);//				dev->trans_start = jiffies;			}			//dev->tbusy = 0;	/* Active upper layer, send again */			//mark above by simon 2001.9.4 for kernel 2.4			//mark_bh(NET_BH); //mark by simon 2001.9.4//		}	}	/* Re-enable interrupt mask */ 	iow(db, 0xff, 0x83);	/* Restore previous register address */	outb(reg_save, db->ioaddr);//	restore_flags(flags);	//dev->interrupt=0;  //mark by simon 2001.9.4            /* release interrupt lock */}/*  Get statistics from driver.*/static struct net_device_stats * dmfe_get_stats(DEVICE *dev){	board_info_t *db = (board_info_t *)dev->priv;	DMFE_DBUG(0, "dmfe_get_stats", 0);//	return &db->stats;}/*  A periodic timer routine  Dynamic media sense, allocated Rx buffer...*/static void dmfe_timer(unsigned long data){	DEVICE *dev = (DEVICE *)data;	board_info_t *db = (board_info_t *)dev->priv;	u8 reg_save, tmp_reg;	DMFE_DBUG(0, "dmfe_timer()", 0);	/* Save previous register address */	reg_save = inb(db->ioaddr);	/* TX timeout check */#if 0	if (dev->trans_start && ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) {		db->device_wait_reset = 1;		db->reset_tx_timeout++;	}	/* DM9000 dynamic RESET check and do */	if (db->device_wait_reset) {		//dev->tbusy = 1; //mark by simon 2001.9.4 for kernel 2.4		netif_stop_queue(dev); // add by simon 2001.9.4 for kernel 2.4		db->reset_counter++;		db->device_wait_reset = 0;		dev->trans_start = 0;		dmfe_init_dm9000(dev);		//mark below by simon 2001.9.4 for kernel 2.4		//dev->tbusy = 0;		/* Active upper layer, send again */		netif_wake_queue(dev); // add by simon 2001.9.4 for kernel 2.4		//mark_bh(NET_BH); //MARK BY SIMON 2001.9.4	}	/* 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);		}	}	/* Restore previous register address */	outb(reg_save, db->ioaddr);	/* Set timer again */	db->timer.expires = DMFE_TIMER_WUT;	add_timer(&db->timer);#endif}/*  Received a packet and pass to upper layer*/static int dmfe_recv(DEVICE *dev){	int i = 0;	static int pktindex = 0;	unsigned long flags;	printk("*** defe_recv\n");	for (i = 0; i < PKTBUFSRX; i++) {		if (rx_pkt.rx_busy[i]) {			pktindex++;			NetReceive(NetRxPackets[i], rx_pkt.rx_pkt_len[i]);//			save_and_cli(flags);			rx_pkt.rx_busy[i] = 0;//			restore_flags(flags);		}	}}static void dmfe_packet_receive(DEVICE *dev){	board_info_t *db = (board_info_t *)(dev->priv);	u8 rxbyte;	u8 *rdptr;	u16 i, RxStatus, RxLen, GoodPacket, tmplen;	unsigned char *packet; 	/* Check packet ready or not */	do {		rxbyte = ior(db, 0xf0);	/* Dummy read */		rxbyte = ior(db, 0xf0);	/* Got most updated data */		/* Status check: this byte must be 0 or 1 */		if (rxbyte > DM9000_PKT_RDY) {			iow(db, 0x05, 0x00);	/* Stop Device */			iow(db, 0xfe, 0x80);	/* Stop INT request */			db->device_wait_reset = 1; 			db->reset_rx_status++;		}		/* packet ready to receive check */		if (rxbyte == DM9000_PKT_RDY) {			/* A packet ready now  & Get status/length */			GoodPacket = 1;			if (db->io_mode == 2) {				/* Byte mode */				RxStatus = ior(db, 0xf2) + (ior(db, 0xf2) << 8);				RxLen = ior(db, 0xf2) + (ior(db, 0xf2) << 8);			} else {				/* Word mode */				outb(0xf2, db->ioaddr);		/*						for(i=0; i<80; i+=2){					if(!(i % 10)) printf("\n");					printf("  %4x  ", inw(db->io_data) );				}				*/		//		RxStatus = inw(db->io_data);		//		RxLen = inw(db->io_data);				RxStatus = inw(db->io_data);				//RxStatus = inw(db->io_data) & 0x00ff;				RxLen = inw(db->io_data);				//i = inw(db->io_data);				//RxLen = ((i & 0xff00) >> 8) | ((i & 0x00ff) << 8);		//printf("RxStatus = %x, RxLen = %x\n",RxStatus,RxLen);			}									/* Packet Status check */			if (RxLen < 0x40) { 				GoodPacket = 0; 				db->runt_length_counter++; 			}			if (RxLen > DM9000_PKT_MAX) { 				printk("<DM9000> RST: RX Len:%x\n", RxLen);				db->device_wait_reset = 1; 				db->long_length_counter++; 			}	//		if (RxStatus & 0xbf00) {			if (RxStatus & 0x00bf) {				GoodPacket = 0;//				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 && rx_pkt.rx_busy[rx_pkt.rxIdx] == 0 ) {					rdptr = (u8*)NetRxPackets[rx_pkt.rxIdx];					/* Read received packet from RX SARM */					if (db->io_mode == 2) {						/* Byte mode */						for (i=0; i<RxLen; i++)							rdptr[i]=inb(db->io_data);					} else {						/* Word mode */						tmplen = (RxLen + 1) / 2;			//printf("Received:");			for (i = 0; i < tmplen; i++){			    ((u16 *)rdptr)[i] = inw(db->io_data);			    //printf("%04x ",((u16 *)rdptr)[i]);			}			//printf("\n");					}					/* Pass to upper layer */			//		db->stats.rx_packets++; 					rx_pkt.rx_pkt_len[rx_pkt.rxIdx] = RxLen;					rx_pkt.rx_busy[rx_pkt.rxIdx] = 1;					rx_pkt.rxIdx++;					rx_pkt.rxIdx = rx_pkt.rxIdx % PKTBUFSRX;				} else {					/* Without buffer or error packet */					if (rx_pkt.rx_busy[rx_pkt.rxIdx] != 0)						printf("No buffer to store Packets\n");					if (db->io_mode == 2) {						/* Byte mode */						for (i = 0; i < RxLen; i++)							inb(db->io_data);					} else {						/* Word mode */						tmplen = (RxLen + 1) / 2;						for (i = 0; i < tmplen; i++)							inw(db->io_data);					}				}			}		}	}while( rxbyte  && !db->device_wait_reset);}/*  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(DEVICE *dev){	board_info_t *db = (board_info_t *)dev->priv;	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->enetaddr[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){	unsigned long Crc = 0xffffffff;	while (Len--) {		Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8);	}	if (flag) return ~Crc;	else 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_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");/* 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){	DEVICE *next_dev;	board_info_t * db;	DMFE_DBUG(0, "clean_module()", 0);	while (dmfe_root_dev) {		next_dev = ((board_info_t *)dmfe_root_dev->priv)->next_dev;		//unregister_netdev(dmfe_root_dev);		db = (board_info_t *)dmfe_root_dev->priv;		release_region(dmfe_root_dev->base_addr, 2);		kfree(db);		/* free board information */		kfree(dmfe_root_dev);	/* free device structure */		dmfe_root_dev = next_dev;	}	DMFE_DBUG(0, "clean_module() exit", 0);}#endif  /* MODULE */

⌨️ 快捷键说明

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