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

📄 dm9xs.c

📁 A Davicom DM9102A NIC fast ethernet driver for Linux.
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* 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(u32 iobase, u8 phy_addr, u8 offset, u32 chip_id)

{

	int i;

	u16 phy_data;

	u32 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(u32 ioaddr, u32 phy_data)

{

	outl(phy_data, ioaddr);			/* MII Clock Low */

	DELAY_1US;

	outl(phy_data | MDCLKH, ioaddr);	/* MII Clock High */

	DELAY_1US;

	outl(phy_data, ioaddr);			/* MII Clock Low */

	DELAY_1US;

}





/*

 *	Read one bit phy data from PHY controller

 */



static u16 phy_read_1bit(u32 ioaddr)

{

	u16 phy_data;



	outl(0x50000, ioaddr);

	DELAY_1US;

	phy_data = ( inl(ioaddr) >> 19 ) & 0x1;

	outl(0x40000, ioaddr);

	DELAY_1US;



	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;

}





/*

 *	Parser SROM and media mode

 */



static void dmfe_parse_srom(struct dmfe_board_info * db)

{

	char * srom = db->srom;

	int dmfe_mode, tmp_reg;



	DMFE_DBUG(0, "dmfe_parse_srom() ", 0);

 

	/* Init CR15 */

	db->cr15_data = CR15_DEFAULT;



	/* Check SROM Version */

	if ( ( (int) srom[18] & 0xff) == SROM_V41_CODE) {

		/* SROM V4.01 */

		/* Get NIC support media mode */

		db->NIC_capability = *(u16 *) (&srom[34]);

		db->PHY_reg4 = 0;

		for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {

			switch( db->NIC_capability & tmp_reg ) {

			case 0x1: db->PHY_reg4 |= 0x0020; break;

			case 0x2: db->PHY_reg4 |= 0x0040; break;

			case 0x4: db->PHY_reg4 |= 0x0080; break;

			case 0x8: db->PHY_reg4 |= 0x0100; break;

			}

		}



		/* Media Mode Force or not check */

		dmfe_mode = *( (int *) &srom[34]) & *( (int *) &srom[36] );

		switch(dmfe_mode) {

		case 0x4: dmfe_media_mode = DMFE_100MHF; break;	/* 100MHF */

		case 0x2: dmfe_media_mode = DMFE_10MFD; break;	/* 10MFD */

		case 0x8: dmfe_media_mode = DMFE_100MFD; break;	/* 100MFD */

		case 0x100:

		case 0x200: dmfe_media_mode = DMFE_1M_HPNA; break;/* HomePNA */

		}



		/* Special Function setting */

		/* VLAN function */

		if ( (SF_mode & 0x1) || (srom[43] & 0x80) ) 

			db->cr15_data |= 0x40;

   

		/* Flow Control */

		if ( (SF_mode & 0x2) || (srom[40] & 0x1) ) 

			db->cr15_data |= 0x400;



		/* TX pause packet */

		if ( (SF_mode & 0x4) || (srom[40] & 0xe) ) 

			db->cr15_data |= 0x9800;

	}



	/* Parse HPNA parameter */

	db->HPNA_command = 1;



	/* Accept remote command or not */

	if (HPNA_rx_cmd == 0)

		db->HPNA_command |= 0x8000;



	 /* Issue remote command & operation mode */

	if (HPNA_tx_cmd == 1)

		switch(HPNA_mode) {	/* Issue Remote Command */

		case 0: db->HPNA_command |= 0x0904; break;

		case 1: db->HPNA_command |= 0x0a00; break;

		case 2: db->HPNA_command |= 0x0506; break;

		case 3: db->HPNA_command |= 0x0602; break;

		}

	else

		switch(HPNA_mode) {	/* Don't Issue */

		case 0: db->HPNA_command |= 0x0004; break;

		case 1: db->HPNA_command |= 0x0000; break;

		case 2: db->HPNA_command |= 0x0006; break;

		case 3: db->HPNA_command |= 0x0002; break;

		}



	/* Check DM9801 or DM9802 present or not */

	db->HPNA_present = 0;

	update_cr6(db->cr6_data|0x40000, db->ioaddr);

	tmp_reg = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);

	if ( ( tmp_reg & 0xfff0 ) == 0xb900 ) {

		/* DM9801 or DM9802 present */

		db->HPNA_timer = 8;

		if ( phy_read(db->ioaddr, db->phy_addr, 31, db->chip_id) == 0x4404) {

			/* DM9801 HomeRun */

			db->HPNA_present = 1;

			dmfe_program_DM9801(db, tmp_reg);

		} else {

			/* DM9802 LongRun */

			db->HPNA_present = 2;

			dmfe_program_DM9802(db);

		}

	}



}





/*

 *	Init HomeRun DM9801

 */



static void dmfe_program_DM9801(struct dmfe_board_info * db, int HPNA_rev)

{

	uint reg17, reg25;



	if ( !HPNA_NoiseFloor ) HPNA_NoiseFloor = DM9801_NOISE_FLOOR;

	switch(HPNA_rev) {

	case 0xb900: /* DM9801 E3 */

		db->HPNA_command |= 0x1000;

		reg25 = phy_read(db->ioaddr, db->phy_addr, 24, db->chip_id);

		reg25 = ( (reg25 + HPNA_NoiseFloor) & 0xff) | 0xf000;

		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);

		break;

	case 0xb901: /* DM9801 E4 */

		reg25 = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);

		reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor;

		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);

		reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor + 3;

		break;

	case 0xb902: /* DM9801 E5 */

	case 0xb903: /* DM9801 E6 */

	default:

		db->HPNA_command |= 0x1000;

		reg25 = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);

		reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor - 5;

		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);

		reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor;

		break;

	}

	phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);

	phy_write(db->ioaddr, db->phy_addr, 17, reg17, db->chip_id);

	phy_write(db->ioaddr, db->phy_addr, 25, reg25, db->chip_id);

}





/*

 *	Init HomeRun DM9802

 */



static void dmfe_program_DM9802(struct dmfe_board_info * db)

{

	uint phy_reg;



	if ( !HPNA_NoiseFloor ) HPNA_NoiseFloor = DM9802_NOISE_FLOOR;

	phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);

	phy_reg = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);

	phy_reg = ( phy_reg & 0xff00) + HPNA_NoiseFloor;

	phy_write(db->ioaddr, db->phy_addr, 25, phy_reg, db->chip_id);

}





/*

 *	Check remote HPNA power and speed status. If not correct, 

 *	issue command again.

*/



static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db)

{

	uint phy_reg;

 

	/* Got remote device status */

	phy_reg = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0x60;

	switch(phy_reg) {

	case 0x00: phy_reg = 0x0a00;break; /* LP/LS */

	case 0x20: phy_reg = 0x0900;break; /* LP/HS */

	case 0x40: phy_reg = 0x0600;break; /* HP/LS */

	case 0x60: phy_reg = 0x0500;break; /* HP/HS */

	}



	/* Check remote device status match our setting ot not */

	if ( phy_reg != (db->HPNA_command & 0x0f00) ) {

		phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);

		db->HPNA_timer=8;

	} else

		db->HPNA_timer=600;	/* Match, every 10 minutes, check */

}







static struct pci_device_id dmfe_pci_tbl[] __initdata = {

	{ 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID },

	{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID },

	{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID },

	{ 0x1282, 0x9009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9009_ID },

	{ 0, }

};

MODULE_DEVICE_TABLE(pci, dmfe_pci_tbl);



static struct pci_driver dmfe_driver = {

	name:		"dm9xs",

	id_table:	dmfe_pci_tbl,

	probe:		dmfe_init_one,

	remove:		dmfe_remove_one,

};



MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");

MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");

MODULE_LICENSE("GPL");	//vika_mo

MODULE_PARM(debug, "i");

MODULE_PARM(mode, "i");

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");



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

	

	DMFE_DBUG(0, "init_module() ", debug);



	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;

	}



	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 = pci_register_driver(&dmfe_driver);

	if (rc < 0)

		return rc;

	if (rc > 0) {

		printk (KERN_INFO "Davicom DM91xx net driver loaded, version "

			DMFE_VERSION "\n");

		return 0;

	}

	return -ENODEV;

}





/*

 *	Description: 

 *	when user used rmmod to delete module, system invoked clean_module()

 *	to un-register all registered services.

 */



void clean_module(void) 

{

	DMFE_DBUG(0, "dmfe_clean_module() ", debug);

	pci_unregister_driver(&dmfe_driver);

}



static void __exit dmfe_cleanup_module(void)

{

	DMFE_DBUG(0, "dmfe_clean_module() ", debug);



	pci_unregister_driver(&dmfe_driver);

}



module_init(dmfe_init_module);

module_exit(dmfe_cleanup_module);

⌨️ 快捷键说明

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