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

📄 dmfe.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		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;	/* Select 10/100M phyxcer */	db->cr6_data &= ~0x40000;	update_cr6(db->cr6_data, db->ioaddr);	/* DM9009 Chip: Phyxcer reg18 bit12=0 */	if (db->chip_id == PCI_DM9009_ID) {		phy_reg = phy_read(db->ioaddr, db->phy_addr, 18, db->chip_id) & ~0x1000;		phy_write(db->ioaddr, db->phy_addr, 18, phy_reg, db->chip_id);	}	/* Phyxcer capability setting */	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;		}		if (db->chip_id == PCI_DM9009_ID) phy_reg &= 0x61;	}  	/* 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 && (db->chip_id == PCI_DM9102_ID) )		phy_write(db->ioaddr, db->phy_addr, 0, 0x1800, db->chip_id);	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 */	/* Transciver Selection */	if (db->op_mode & 0x10)		/* 1M HomePNA */		db->cr6_data |= 0x40000;/* External MII select */	else		db->cr6_data &= ~0x40000;/* Internal 10/100 transciver */	update_cr6(db->cr6_data, db->ioaddr);	/* 10/100M phyxcer force mode need */	if ( !(db->media_mode & 0x18)) {		/* Forece Mode */		phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);		if ( !(phy_reg & 0x1) ) {			/* parter without N-Way capability */			phy_reg = 0x0;			switch(db->op_mode) {			case DMFE_10MHF: phy_reg = 0x0; break;			case DMFE_10MFD: phy_reg = 0x100; break;			case DMFE_100MHF: phy_reg = 0x2000; break;			case DMFE_100MFD: phy_reg = 0x2100; break;			}			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);       			if ( db->chip_type && (db->chip_id == PCI_DM9102_ID) )				mdelay(20);			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);		}	}}/* *	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 address */		for (i = 0x10; i > 0; i = i >> 1)			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);		/* Send register address */		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 address */		for (i = 0x10; i > 0; i = i >> 1)			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);		/* Send register address */		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){	outl(phy_data, ioaddr);			/* MII Clock Low */	udelay(1);	outl(phy_data | MDCLKH, ioaddr);	/* MII Clock High */	udelay(1);	outl(phy_data, ioaddr);			/* MII Clock Low */	udelay(1);}/* *	Read one bit phy data from PHY controller */static u16 phy_read_1bit(unsigned long ioaddr){	u16 phy_data;	outl(0x50000, ioaddr);	udelay(1);	phy_data = ( inl(ioaddr) >> 19 ) & 0x1;	outl(0x40000, ioaddr);	udelay(1);	return phy_data;}/* *	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 = le16_to_cpup((__le16 *)srom + 34/2);		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 = le32_to_cpup((__le32 *)srom + 34/4) &				le32_to_cpup((__le32 *)srom + 36/4);		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[] = {	{ 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		= "dmfe",	.id_table	= dmfe_pci_tbl,	.probe		= dmfe_init_one,	.remove		= __devexit_p(dmfe_remove_one),};MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);module_param(debug, int, 0);module_param(mode, byte, 0);module_param(cr6set, int, 0);module_param(chkmode, byte, 0);module_param(HPNA_mode, byte, 0);module_param(HPNA_rx_cmd, byte, 0);module_param(HPNA_tx_cmd, byte, 0);module_param(HPNA_NoiseFloor, byte, 0);module_param(SF_mode, byte, 0);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);	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_module_init(&dmfe_driver);	if (rc < 0)		return rc;	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);	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 + -