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

📄 ethernet driver for linux.txt

📁 Linux下的以太网驱动
💻 TXT
📖 第 1 页 / 共 4 页
字号:

static void allocate_rx_buffer(struct dmfe_board_info *db)
{
	struct rx_desc *rxptr;
	struct sk_buff *skb;

	rxptr = db->rx_insert_ptr;

	while(db->rx_avail_cnt < RX_DESC_CNT) {
		if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
			break;
		rxptr->rx_skb_ptr = skb; /* FIXME (?) */
		rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
		wmb();
		rxptr->rdes0 = cpu_to_le32(0x80000000);
		rxptr = rxptr->next_rx_desc;
		db->rx_avail_cnt++;
	}

	db->rx_insert_ptr = rxptr;
}


/*
 *	Read one word data from the serial ROM
 */

static u16 read_srom_word(long ioaddr, int offset)
{
	int i;
	u16 srom_data = 0;
	long cr9_ioaddr = ioaddr + DCR9;

	outl(CR9_SROM_READ, cr9_ioaddr);
	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);

	/* Send the Read Command 110b */
	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
	SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);

	/* Send the offset */
	for (i = 5; i >= 0; i--) {
		srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
		SROM_CLK_WRITE(srom_data, cr9_ioaddr);
	}

	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);

	for (i = 16; i > 0; i--) {
		outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
		udelay(5);
		srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
		outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
		udelay(5);
	}

	outl(CR9_SROM_READ, cr9_ioaddr);
	return srom_data;
}


/*
 *	Auto sense the media mode
 */

static u8 dmfe_sense_speed(struct dmfe_board_info * db)
{
	u8 ErrFlag = 0;
	u16 phy_mode0,phy_mode1,phy_mode25;

	phy_mode0 = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
	phy_mode1 = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
	phy_mode25 = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);
    

	if ( (phy_mode0 & 0x1000)&& (phy_mode1&0x0020)) {
		switch ((phy_mode25&3)|(phy_mode0&0x100)) {
		case 0x002: db->op_mode = DMFE_10MHF; break;
		case 0x102: db->op_mode = DMFE_10MFD; break;
		case 0x001: db->op_mode = DMFE_100MHF; break;
		case 0x101: db->op_mode = DMFE_100MFD; break;
		default: db->op_mode = DMFE_100MHF;
			ErrFlag = 1;
			break;
		}
	} else {
		db->op_mode = DMFE_100MHF;
		ErrFlag = 1;
	}

	return ErrFlag;
}


/*
 *	Set 10/100 phyxcer capability
 *	AUTO mode : phyxcer register4 is NIC capability
 *	Force mode: phyxcer register4 is the force media
 */

static void dmfe_set_phyxcer(struct dmfe_board_info *db)
{
	u16 phy_reg;

//    printk("retart auto negotiation, tester is ljq\n");//add by ljq
	/* restart auto negotion */
	phy_reg = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
//    printk("the phy_reg is %x\n",phy_reg);//add by ljq
//    udelay(10000);//add by ljq
	phy_write(db->ioaddr, db->phy_addr, 0, 0x200|phy_reg, db->chip_id);

	/* Phyxcer capability setting */
	do {
	  phy_reg = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
	} while (phy_reg & 0x20 == 0);
// 	printk("the tester is ljq, display the value of phy_reg\n");//add by ljq
    printk("auto negation status %x\n", phy_reg);
	   
// 	printk("the tester is ljq, display the value of phy_reg\n");//add by ljq
//  phy_reg = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);//add by ljq
//  printk("the 1 register status is %x\n",  phy_reg);//add by ljq

	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id);
	printk("auto negation offset 4=%x\n", phy_reg);

    
//   phy_write(db->ioaddr, db->phy_addr, 4 , 0x0000, db->chip_id);//add by ljq
// 	 printk("the tester is ljq, display the value of phy_reg\n");//add by ljq
//    phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id);//add by ljq
//    printk("the register 4 after chang the value is %x\n",phy_reg);//add by ljq

    
    
    phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;

	
	if (db->media_mode & DMFE_AUTO) {
		/* AUTO Mode */
		phy_reg |= db->PHY_reg4;
	} else {
		/* Force Mode */
		switch(db->media_mode) {
		case DMFE_10MHF: phy_reg |= 0x20; break;
		case DMFE_10MFD: phy_reg |= 0x40; break;
		case DMFE_100MHF: phy_reg |= 0x80; break;
		case DMFE_100MFD: phy_reg |= 0x100; break;
		}
	}

  	/* Write new capability to Phyxcer Reg4 */
	if ( !(phy_reg & 0x01e0)) {
		phy_reg|=db->PHY_reg4;
		db->media_mode|=DMFE_AUTO;
	}
	phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);

 	/* Restart Auto-Negotiation */
	if ( !db->chip_type )
		phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
}


/*
 *	Process op-mode
 *	AUTO mode : PHY controller in Auto-negotiation Mode
 *	Force mode: PHY controller in force mode with HUB
 *			N-way force capability with SWITCH
 */

static void dmfe_process_mode(struct dmfe_board_info *db)
{
	u16 phy_reg;

	/* Full Duplex Mode Check */
	if (db->op_mode & 0x4)
		db->cr6_data |= CR6_FDM;	/* Set Full Duplex Bit */
	else
		db->cr6_data &= ~CR6_FDM;	/* Clear Full Duplex Bit */

	update_cr6(db->cr6_data, db->ioaddr);

}


/*
 *	Write a word to Phy register
 */

static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
{
	u16 i;
	unsigned long ioaddr;

	if (chip_id == PCI_DM9132_ID) {
		ioaddr = iobase + 0x80 + offset * 4;
		outw(phy_data, ioaddr);
	} else {
		/* DM9102/DM9102A Chip */
		ioaddr = iobase + DCR9;

		/* Send 33 synchronization clock to Phy controller */
		for (i = 0; i < 35; i++)
			phy_write_1bit(ioaddr, PHY_DATA_1);

		/* Send start command(01) to Phy */
		phy_write_1bit(ioaddr, PHY_DATA_0);
		phy_write_1bit(ioaddr, PHY_DATA_1);

		/* Send write command(01) to Phy */
		phy_write_1bit(ioaddr, PHY_DATA_0);
		phy_write_1bit(ioaddr, PHY_DATA_1);

		/* Send Phy addres */
		for (i = 0x10; i > 0; i = i >> 1)
			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);

		/* Send register addres */
		for (i = 0x10; i > 0; i = i >> 1)
			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);

		/* written trasnition */
		phy_write_1bit(ioaddr, PHY_DATA_1);
		phy_write_1bit(ioaddr, PHY_DATA_0);

		/* Write a word data to PHY controller */
		for ( i = 0x8000; i > 0; i >>= 1)
			phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
	}
}


/*
 *	Read a word data from phy register
 */

static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
{
	int i;
	u16 phy_data;
	unsigned long ioaddr;

	if (chip_id == PCI_DM9132_ID) {
		/* DM9132 Chip */
		ioaddr = iobase + 0x80 + offset * 4;
		phy_data = inw(ioaddr);
	} else {
		/* DM9102/DM9102A Chip */
		ioaddr = iobase + DCR9;

      	/* Send 33 synchronization clock to Phy controller */
		for (i = 0; i < 35; i++)
			phy_write_1bit(ioaddr, PHY_DATA_1);
      
		/* Send start command(01) to Phy */
		phy_write_1bit(ioaddr, PHY_DATA_0);
		phy_write_1bit(ioaddr, PHY_DATA_1);

		/* Send read command(10) to Phy */
		phy_write_1bit(ioaddr, PHY_DATA_1);
		phy_write_1bit(ioaddr, PHY_DATA_0);

		/* Send Phy addres */
		for (i = 0x10; i > 0; i = i >> 1)
			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);

		/* Send register addres */
		for (i = 0x10; i > 0; i = i >> 1)
			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);

		/* Skip transition state */
		phy_read_1bit(ioaddr);

		/* read 16bit data */
		for (phy_data = 0, i = 0; i < 16; i++) {
			phy_data <<= 1;
			phy_data |= phy_read_1bit(ioaddr);
		}
	}

	return phy_data;
}


/*
 *	Write one bit data to Phy Controller
 */

static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
{
//  int i;//add by ljq
    
    phy_data |=1<<18;	
	outl(phy_data, ioaddr);			/* MII Clock Low */
	inl(ioaddr);
	udelay(1);
//    for (i=1; i>0; i--);//add by ljq
	outl(phy_data | MDCLKH, ioaddr);	/* MII Clock High */
	inl(ioaddr);
	udelay(1);
//    for (i=1; i>0; i--);//add by ljq
	outl(phy_data, ioaddr);			/* MII Clock Low */
	inl(ioaddr);
	udelay(1);
//    for (i=1; i>0; i--); //add by ljq
}


/*
 *	Read one bit phy data from PHY controller
 */

static u16 phy_read_1bit(unsigned long ioaddr)
{
	u16 phy_data;

	//outl(0x50000, ioaddr);
	outl(0x10000, ioaddr);
	inl(ioaddr);
	udelay(1);
	phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
	//outl(0x40000, ioaddr);
	outl(0x00000, ioaddr);
	inl(ioaddr);
	udelay(1);

	return phy_data;
}


/*
 *	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)
 */

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;
}

static int gc_dmfe_info_read (char *page, char **start, off_t off,
		int count, int *eof, void *data)
{
	int len =0;
	struct dmfe_board_info *db = (struct dmfe_board_info *)data;
	struct tx_desc *tmp_tx;
	struct rx_desc *tmp_rx;
	unsigned long ioaddr = db->ioaddr;
	int i;
	
	len +=sprintf(page+len, "CSR0: %x\n", inl(ioaddr+DCR0));
	len +=sprintf(page+len, "CSR1: %x\n", inl(ioaddr+DCR1));
	len +=sprintf(page+len, "CSR2: %x\n", inl(ioaddr+DCR2));
	len +=sprintf(page+len, "CSR3: %x\n", inl(ioaddr+DCR3));
	len +=sprintf(page+len, "CSR4: %x\n", inl(ioaddr+DCR4));
	len +=sprintf(page+len, "CSR5: %x\n", inl(ioaddr+DCR5));
	len +=sprintf(page+len, "CSR6: %x\n", inl(ioaddr+DCR6));
	len +=sprintf(page+len, "CSR7: %x\n", inl(ioaddr+DCR7));

	len += sprintf(page+len, "Tx descriptores:\n");
	for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
		len += sprintf(page+len, "Tx %d:\n", i);
		len += sprintf(page+len, "\ttdes0 %08x\n",tmp_tx->tdes0);
		len += sprintf(page+len, "\ttdes1 %08x\n",tmp_tx->tdes1);	
		len += sprintf(page+len, "\ttdes2 %08x\n",tmp_tx->tdes2);
		len += sprintf(page+len, "\ttdes3 %08x\n",tmp_tx->tdes3);
	}
	len += sprintf(page+len, "Rx descriptores\n");
	for(tmp_rx =db->first_rx_desc, i=0; i<RX_DESC_CNT; i++, tmp_rx++){
		len += sprintf(page+len, "Rx %d:\n", i);
		len += sprintf(page+len, "\trdes0 %08x\n", tmp_rx->rdes0);
		len += sprintf(page+len, "\trdes1 %08x\n", tmp_rx->rdes1);
		len += sprintf(page+len, "\trdes2 %08x\n", tmp_rx->rdes2);
		len += sprintf(page+len, "\trdes3 %08x\n", tmp_rx->rdes3);
	}
	  
	len += sprintf(page+len, "phy addr:\n");
	for(i=0;i<32;i++)
	{
	u16 data;
	data=phy_read(db->ioaddr, db->phy_addr, i, db->chip_id);
	len += sprintf(page+len, "%d:%04x\n",i, data);
	}

	*eof = 1;
	return len;
}

MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");
MODULE_LICENSE("GPL");

//MODULE_PARM(debug,int,S_IRUGO);
//MODULE_PARM(mode, char,S_IRUGO);
//MODULE_PARM(cr6set, "i");
//MODULE_PARM(chkmode, "i");
//MODULE_PARM(HPNA_mode, "i");
//MODULE_PARM(HPNA_rx_cmd, "i");
//MODULE_PARM(HPNA_tx_cmd, "i");
//MODULE_PARM(HPNA_NoiseFloor, "i");
//MODULE_PARM(SF_mode, "i");
//MODULE_PARM_DESC(debug, "Davicom DM9xxx enable debugging (0-1)");
//MODULE_PARM_DESC(mode, "Davicom DM9xxx: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
//MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function (bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)");

/*	Description:
 *	when user used insmod to add module, system invoked init_module()
 *	to initilize and register.
 */

static int __init dmfe_init_module(void)
{
	int rc;

//	printk(version);
//	printed_version = 1;

//	DMFE_DBUG(0, "init_module() ", debug);
	printk("ITC MAC 10/100M Fast Ethernet Adapter driver 1.0 init\n");
	if (debug)
		dmfe_debug = debug;	/* set debug flag */
	if (cr6set)
		dmfe_cr6_user_set = cr6set;

 	switch(mode) {
   	case DMFE_10MHF:
	case DMFE_100MHF:
	case DMFE_10MFD:
	case DMFE_100MFD:
	case DMFE_1M_HPNA:
		dmfe_media_mode = mode;
		break;
	default:dmfe_media_mode = DMFE_AUTO;
		break;
	}
#ifdef NO_PHY_PROBE
//	mode=dmfe_media_mode=DMFE_100MHF;
	mode=dmfe_media_mode=DMFE_100MFD;
#endif

	if (HPNA_mode > 4)
		HPNA_mode = 0;		/* Default: LP/HS */
	if (HPNA_rx_cmd > 1)
		HPNA_rx_cmd = 0;	/* Default: Ignored remote cmd */
	if (HPNA_tx_cmd > 1)
		HPNA_tx_cmd = 0;	/* Default: Don't issue remote cmd */
	if (HPNA_NoiseFloor > 15)
		HPNA_NoiseFloor = 0;

	rc = dmfe_init_one(SOC_SOC_DMFE1_BASE,SOC_SOC_DMFE1_IRQ);
	if (rc < 0)
		return rc;

	hwaddr[5]++;
  rc = dmfe_init_one(SOC_SOC_DMFE2_BASE,SOC_SOC_DMFE2_IRQ);
	return 0;
}


/*
 *	Description:
 *	when user used rmmod to delete module, system invoked clean_module()
 *	to un-register all registered services.
 */

static void __exit dmfe_cleanup_module(void)
{
//	DMFE_DBUG(0, "dmfe_clean_module() ", debug);
	dmfe_remove_one(SOC_SOC_DMFE1_BASE);
	dmfe_remove_one(SOC_SOC_DMFE2_BASE);
	printk("ITC MAC 10/100M Fast Ethernet Adapter driver 1.0 init cleanup\n");
}

module_init(dmfe_init_module);
module_exit(dmfe_cleanup_module);

⌨️ 快捷键说明

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