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

📄 dm9000x.c

📁 S3C2410硬件平台的LINUX DM9000AE驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	                dev->dev_addr[i] = eth3_mac_addr[i];//db->srom[i];	          //      printk("%02X:",dev->dev_addr[i]);	        }		//printk("\n");			}else		return 0;	//printk("HHTech <DM9000> I/O: %x, VID:   succ\n", iobase);	//return;	//printk("Device Name=%s,name=%s\n",dev->name,dev->priv);	//DMFE_DBUG(0, "dmfe_probe()",0);	//iow(db, 0xfe, 0x0f); 	/* Clear interrupt status */	//printk("222\n");	/* Disable all interrupt */	//iow(db, 0xff, 0x80);/////////////////////////////////////////////////////////////////////////	/* Search All DM9000 NIC */	//{	//printk("iobase=%x,value=%x\n",iobase,DM9000_VID_L);			outb(DM9000_VID_L, iobase);	id_val = inb(iobase + 4);	outb(DM9000_VID_H, iobase);	id_val |= inb(iobase + 4) << 8;	outb(DM9000_PID_L, iobase);	id_val |= inb(iobase + 4) << 16;	outb(DM9000_PID_H, iobase);	id_val |= inb(iobase + 4) << 24;	if (id_val == DM9000_ID) {	    printk("HHTech DM9000 %s I/O: %x,VID: %x,MAC: ", dev->name,iobase, id_val);	    dm9000_count++;	    /* Init network device */	    dev = init_etherdev(dev, 0); 	/* Allocated board information structure */	irqline = 3;	db = (void *)(kmalloc(sizeof(*db), GFP_KERNEL|GFP_DMA));	memset(db, 0, sizeof(*db));	dev->priv = db;	/* link device and board info */	db->next_dev = dmfe_root_dev;	dmfe_root_dev = dev;	db->ioaddr = iobase;	db->io_data = iobase + 4;	/* driver system function */	dev->base_addr = iobase;	//dev->irq = 68; //INT4 166;//irqline;	dev->open = &dmfe_open;	dev->hard_start_xmit = &dmfe_start_xmit;	dev->stop = &dmfe_stop;	dev->get_stats = &dmfe_get_stats;	dev->set_multicast_list = &dm9000_hash_table;	dev->do_ioctl = &dmfe_do_ioctl;	/* Read SROM content */	/*for (i=0; i<64; i++)		((u16 *)db->srom)[i] = read_srom_word(db, i);*/		/* Set Node Address */		//add by zy		//i2c_read(0x7a,buff,6);		//we set lan-switch data to first 24 bytes,then put mac data to the last 6 bytes.		//printk("MAC set to ");		for (i=0; i<6; i++){	//	    dev->dev_addr[i] = eth_mac_addr[i];//db->srom[i];		    printk("%02X:",dev->dev_addr[i]);		}		printk("\n");	}	if (dm9000_count) {	//request_irq(db->irq, &dmfe_interrupt,0,"DM9000 device",dev);/* Enable interrupts for GPIO6 *///L-->H//HHTECH//*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_GPIOINTENABLE)) |=0x00000040;/* Enable interrupt level for GPIO6 - VEC38 *///*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_INTLEVEL5)) |=0x04000000;	}//printk("**** request_irq=%x\n",dev->irq);//if(request_irq(dev->irq, &dmfe_interrupt,SA_SHIRQ,"DM9000 device",dev))  //              return -EAGAIN;//	printk(" ****** success  rquest_irq\n");	/* Re-enable interrupt mask */	//iow(db, 0xff, 0x83);	return dm9000_count ? 0:-ENODEV;}/*  Open the interface.  The interface is opened whenever "ifconfig" actives it.*/static int dmfe_open(struct DEVICE *dev){	board_info_t * db = (board_info_t *)dev->priv;	DMFE_DBUG(0, "dmfe_open", 0);	//minor = MINOR(dev->priv);	//printk("minor=%x\n",dev->minor);	//if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev))	//printk("request_irq,irq=%x\n",dev->irq);	if(request_irq(dev->irq, &dmfe_interrupt,SA_INTERRUPT/*SA_SHIRQ*/,"DM9000 device",dev))		return -EAGAIN;	/* Initilize DM910X board */	dmfe_init_dm9000(dev); //	printk("end init\n");	/* Init driver variable */	db->dbug_cnt = 0;	db->runt_length_counter = 0;	db->long_length_counter = 0;	db->reset_counter = 0;	/* Active System Interface */	//dev->tbusy = 0;	/* Can transmit packet */	//dev->start = 1;	/* interface ready */	//mark above for kernel 2.4	netif_wake_queue(dev);         //add by simon 2001.9.4 for kernel 2.4	MOD_INC_USE_COUNT;//	printk("init timer\n");	/* set and active a timer process */	init_timer(&db->timer);//	printk("end timer\n");	db->timer.expires = DMFE_TIMER_WUT * 2;	db->timer.data = (unsigned long)dev;	db->timer.function = &dmfe_timer;	add_timer(&db->timer);	return 0;}/* Set PHY operationg mode*/static void set_PHY_mode(board_info_t *db){	u16 phy_reg4 = 0x01e1, phy_reg0=0x1000;	if ( !(db->op_mode & DM9000_AUTO) ) {		switch(db->op_mode) {		case DM9000_10MHD: phy_reg4 = 0x21;                              phy_reg0 = 0x0000; break;		case DM9000_10MFD: phy_reg4 = 0x41;                              //phy_reg0 = 0x0100;                                phy_reg0 = 0x1100; //add by simon 2001.11.8                              break;                       		case DM9000_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break;		case DM9000_100MFD: phy_reg4 = 0x101; 				//phy_reg0 = 0x2100; 				  phy_reg0 =0x3100; //add by simon 2001.11.8                                break;		}		phy_write(db, 4, phy_reg4);	/* Set PHY media mode */		phy_write(db, 0, phy_reg0);	/*  Tmp */	}	iow(db, 0x1e, 0x01);		/* Let GPIO0 output */	iow(db, 0x1f, 0x00);		/* Enable PHY */}/*	Init HomeRun DM9801*/static void program_dm9801(board_info_t *db, u16 HPNA_rev){	__u16 reg16, reg17, reg24, reg25;	if ( !nfloor ) nfloor = DM9801_NOISE_FLOOR;	reg16 = phy_read(db, 16);	reg17 = phy_read(db, 17);	reg24 = phy_read(db, 24);	reg25 = phy_read(db, 25);	switch(HPNA_rev) {	case 0xb900: /* DM9801 E3 */		reg16 |= 0x1000;		reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xf000;		break;	case 0xb901: /* DM9801 E4 */		reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xc200;		reg17 = (reg17 & 0xfff0) + nfloor + 3;		break;	case 0xb902: /* DM9801 E5 */	case 0xb903: /* DM9801 E6 */	default:		reg16 |= 0x1000;		reg25 = ( (reg24 + nfloor - 3) & 0x00ff) | 0xc200;		reg17 = (reg17 & 0xfff0) + nfloor;		break;	}	phy_write(db, 16, reg16);	phy_write(db, 17, reg17);	phy_write(db, 25, reg25);}/*	Init LongRun DM9802*/static void program_dm9802(board_info_t *db){	__u16 reg25;	if ( !nfloor ) nfloor = DM9802_NOISE_FLOOR;	reg25 = phy_read(db, 25);	reg25 = (reg25 & 0xff00) + nfloor;	phy_write(db, 25, reg25);}/* Identify NIC type*/static void identify_nic(board_info_t *db){	u16 phy_reg3;	iow(db, 0, DM9000_EXT_MII);	phy_reg3 = phy_read(db, 3);	switch(phy_reg3 & 0xfff0) {	case 0xb900:		if (phy_read(db, 31) == 0x4404) {			db->nic_type =  HOMERUN_NIC;			program_dm9801(db, phy_reg3);		} else {			db->nic_type = LONGRUN_NIC;			program_dm9802(db);		}		break;	default: db->nic_type = FASTETHER_NIC; break;	}	iow(db, 0, DM9000_INT_MII);	}/* Initilize dm9000 board*/static void dmfe_init_dm9000(struct DEVICE *dev){	board_info_t *db = (board_info_t *)dev->priv; 	DMFE_DBUG(0, "dmfe_init_dm9000()", 0);	/* RESET device */	iow(db, 0, 1);	udelay(100);	/* delay 100us */	/* I/O mode */	db->io_mode = ior(db, 0xfe) >> 6; 	/* ISR bit7:6 keeps I/O mode */	/* NIC Type: FASTETHER, HOMERUN, LONGRUN */	identify_nic(db);		/* Set PHY */	db->op_mode = media_mode;	set_PHY_mode(db);	/* Init needed register value */	db->reg0 = DM9000_REG00;	if ( (db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA) )		db->reg0 |= DM9000_EXT_MII;		/* User passed argument */	db->reg5 = reg5;	db->reg8 = reg8;	db->reg9 = reg9;	db->rega = rega;	/* Program operating register */	iow(db, 0x00, db->reg0);	iow(db, 0x02, 0);	/* TX Polling clear */	iow(db, 0x08, 0x3f);	/* Less 3Kb, 200us */	iow(db, 0x09, db->reg9);/* Flow Control : High/Low Water */	iow(db, 0x0a, db->rega);/* Flow Control */	iow(db, 0x2f, 0);	/* Special Mode */	iow(db, 0x01, 0x2c);	/* clear TX status */	iow(db, 0xfe, 0x0f); 	/* Clear interrupt status */ 	/* Re-enable interrupt mask */	iow(db, 0xff, 0x83);	/* Set address filter table */	dm9000_hash_table(dev);	/* 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 = 1;	db->tx_pkt_cnt = 0;	db->queue_pkt_len = 0;	dev->trans_start = 0;//HHTECH/hn: to solve reboot problem: //../5307/ints.c(47): default irq handler vec=166 [0xa6]/* Enable interrupts for GPIO6 *///L-->H//*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_GPIOINTENABLE)) |=0x00000040;/* Enable interrupt level for GPIO6 - VEC38 *///*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_INTLEVEL5)) |=0x04000000;	        //HHTECH#if 0switch(dev->irq){	case 68:*(volatile unsigned long *)0x10000034|=0x10000000;		*(volatile unsigned long *)0x10000020|=0x000b0000;		break;	case 90:*(volatile unsigned long *)0x10000034|=0x00000040;		*(volatile unsigned long *)0x1000002c|=0x0b000000;		break;	case 91:*(volatile unsigned long *)0x10000034|=0x00000020;		*(volatile unsigned long *)0x1000002c|=0x00b00000;	}	#endif	/////////////////////////////////////////////////////////////////////	spin_lock_init(&db->lock); //add by simon 2001.9.7 init the spinlock var}/*  Hardware start transmission.  Send a packet to media from the upper layer.*/static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev){	board_info_t *db = (board_info_t *)dev->priv;	char * data_ptr;	int i, tmplen;		DMFE_DBUG(0, "dmfe_start_xmit", 0);	/* Resource flag check */	//if ( test_and_set_bit(0, (void *)&dev->tbusy) || (db->tx_pkt_cnt > 1) )	//	return 1;	//mark above by simon 2001.9.4 for kernel 2.4	if (db->tx_pkt_cnt > 1) return 1; //add by simon 2001.9.4	netif_stop_queue(dev); //add by simon 2001.9.4 for kernel 2.4	/* Disable all interrupt */	iow(db, 0xff, 0x80);	/* Move data to DM9000 TX RAM */	data_ptr = (char *)skb->data;	outb(0xf8, db->ioaddr);	tmplen = (skb->len + 1) / 2;	/* Word mode*/ 	for (i = 0; i < tmplen; i++)      		outw(((u16 *)data_ptr)[i], db->io_data); 		/* 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 */		dev->trans_start = jiffies;	/* saved the time stamp */	} 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)	        //clear_bit(0, (void*)&dev->tbusy); //mark by simon 2001.9.4 for kernel 2.4               netif_wake_queue(dev);   //add by simon 2001.9.4 for kernel 2.4			/* Re-enable interrupt mask */ 	iow(db, 0xff, 0x83);	return 0;}/*  Stop the interface.  The interface is stopped when it is brought.*/static int dmfe_stop(struct DEVICE *dev){	board_info_t *db = (board_info_t *)dev->priv;	DMFE_DBUG(0, "dmfe_stop", 0);	/* deleted timer */	del_timer(&db->timer);	/* disable system */	//dev->start = 0;	/* interface disable */	//dev->tbusy = 1;	/* can't transmit */	//mark above by simon 2001.9.4	netif_stop_queue(dev);  //add by simon 2001.9.4 for kernel 2.4	/* 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 */	MOD_DEC_USE_COUNT;	/* 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	return 0;}/*  DM9102 insterrupt handler  receive the packet to upper layer, free the transmitted packet*/static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct DEVICE *dev = dev_id;	board_info_t *db;	int int_status, tx_status;	u8 reg_save;	//printk("Intrrupt happened\n");	DMFE_DBUG(0, "dmfe_interrupt()", 0);	if (!dev) {		DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);		return;	}        //mark below if-block by simon 2001.9.4           // for kernel 2.4 

⌨️ 快捷键说明

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