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

📄 dmfe.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	DMFE_DBUG(0, "dmfe_descriptor_init()", 0);	/* tx descriptor start pointer */	db->tx_insert_ptr = db->first_tx_desc;	db->tx_remove_ptr = db->first_tx_desc;	outl(virt_to_bus(db->first_tx_desc), ioaddr + DCR4);	/* Init CR4 */	/* rx descriptor start pointer */	db->first_rx_desc = (struct rx_desc *)	    ((u32) db->first_tx_desc + sizeof(struct rx_desc) * TX_DESC_CNT);	db->rx_insert_ptr = db->first_rx_desc;	db->rx_ready_ptr = db->first_rx_desc;	outl(virt_to_bus(db->first_rx_desc), ioaddr + DCR3);	/* Init CR3 */	/* Init Transmit chain */	tmp_buf = db->buf_pool_start;	for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {		tmp_tx->tx_buf_ptr = (u32) tmp_buf;		tmp_tx->tdes0 = 0;		tmp_tx->tdes1 = 0x81000000;	/* IC, chain */		tmp_tx->tdes2 = (u32) virt_to_bus(tmp_buf);		tmp_tx->tdes3 = (u32) virt_to_bus(tmp_tx) + sizeof(struct tx_desc);		tmp_tx->next_tx_desc = (u32) ((u32) tmp_tx + sizeof(struct tx_desc));		tmp_buf = (unsigned char *) ((u32) tmp_buf + TX_BUF_ALLOC);	}	(--tmp_tx)->tdes3 = (u32) virt_to_bus(db->first_tx_desc);	tmp_tx->next_tx_desc = (u32) db->first_tx_desc;	/* Init Receive descriptor chain */	for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {		tmp_rx->rdes0 = 0;		tmp_rx->rdes1 = 0x01000600;		tmp_rx->rdes3 = (u32) virt_to_bus(tmp_rx) + sizeof(struct rx_desc);		tmp_rx->next_rx_desc = (u32) ((u32) tmp_rx + sizeof(struct rx_desc));	}	(--tmp_rx)->rdes3 = (u32) virt_to_bus(db->first_rx_desc);	tmp_rx->next_rx_desc = (u32) db->first_rx_desc;	/* pre-allocated Rx buffer */	allocated_rx_buffer(db);}/*   Update CR6 vaule   Firstly stop DM910X , then written value and start */static void update_cr6(u32 cr6_data, u32 ioaddr){	u32 cr6_tmp;	cr6_tmp = cr6_data & ~0x2002;	/* stop Tx/Rx */	outl(cr6_tmp, ioaddr + DCR6);	DELAY_5US;	outl(cr6_data, ioaddr + DCR6);	cr6_tmp = inl(ioaddr + DCR6);	/* printk("CR6 update %x ", cr6_tmp); */}/* Send a setup frame for DM9132   This setup frame initilize DM910X addres filter mode */static void dm9132_id_table(struct net_device *dev, int mc_cnt){	struct dev_mc_list *mcptr;	u16 *addrptr;	u32 ioaddr = dev->base_addr + 0xc0;	/* ID Table */	u32 hash_val;	u16 i, hash_table[4];	DMFE_DBUG(0, "dm9132_id_table()", 0);	/* Node address */	addrptr = (u16 *) dev->dev_addr;	outw(addrptr[0], ioaddr);	ioaddr += 4;	outw(addrptr[1], ioaddr);	ioaddr += 4;	outw(addrptr[2], ioaddr);	ioaddr += 4;	/* 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 (mcptr = dev->mc_list, 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; i < 4; i++, ioaddr += 4) {		outw(hash_table[i], ioaddr);	}}/* Send a setup frame for DM9102/DM9102A   This setup frame initilize DM910X addres filter mode */static void send_filter_frame(struct net_device *dev, int mc_cnt){	struct dmfe_board_info *db = dev->priv;	struct dev_mc_list *mcptr;	struct tx_desc *txptr;	u16 *addrptr;	u32 *suptr;	int i;	DMFE_DBUG(0, "send_filetr_frame()", 0);	txptr = db->tx_insert_ptr;	suptr = (u32 *) txptr->tx_buf_ptr;	/* Node address */	addrptr = (u16 *) dev->dev_addr;	*suptr++ = addrptr[0];	*suptr++ = addrptr[1];	*suptr++ = addrptr[2];	/* broadcast address */	*suptr++ = 0xffff;	*suptr++ = 0xffff;	*suptr++ = 0xffff;	/* fit the multicast address */	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {		addrptr = (u16 *) mcptr->dmi_addr;		*suptr++ = addrptr[0];		*suptr++ = addrptr[1];		*suptr++ = addrptr[2];	}	for (; i < 14; i++) {		*suptr++ = 0xffff;		*suptr++ = 0xffff;		*suptr++ = 0xffff;	}	/* prepare the setup frame */	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;	txptr->tdes1 = 0x890000c0;	/* Resource Check and Send the setup packet */	if (!db->tx_packet_cnt) {		/* Resource Empty */		db->tx_packet_cnt++;		txptr->tdes0 = 0x80000000;		update_cr6(db->cr6_data | 0x2000, dev->base_addr);		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling command */		update_cr6(db->cr6_data, dev->base_addr);	} else {		/* Put into TX queue */		db->tx_queue_cnt++;	}}/* *	Allocate rx buffer, *	Allocate as many Rx buffers as possible. */static void allocated_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 = alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC)) == NULL)			break;		rxptr->rx_skb_ptr = (u32) skb;		rxptr->rdes2 = virt_to_bus(skb->tail);		rxptr->rdes0 = 0x80000000;		rxptr = (struct rx_desc *) 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);		DELAY_5US;		srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);		outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);		DELAY_5US;	}	outl(CR9_SROM_READ, cr9_ioaddr);	return srom_data;}/* *	Auto sense the media mode */ static void dmfe_sense_speed(struct dmfe_board_info *db){	int i;	u16 phy_mode;	for (i = 1000; i; i--) {		DELAY_5US;		phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);		if ((phy_mode & 0x24) == 0x24)			break;	}	if (i) {		if (db->chip_id == PCI_DM9132_ID)	/* DM9132 */			phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;		else		/* DM9102/DM9102A */			phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;		/* printk("Phy_mode %x ",phy_mode); */		switch (phy_mode) {		case 0x1000:			db->op_mode = DMFE_10MHF;			break;		case 0x2000:			db->op_mode = DMFE_10MFD;			break;		case 0x4000:			db->op_mode = DMFE_100MHF;			break;		case 0x8000:			db->op_mode = DMFE_100MFD;			break;		default:			db->op_mode = DMFE_10MHF;			DMFE_DBUG(0, "Media Type error, phy reg17", phy_mode);			break;		}	} else {		db->op_mode = DMFE_10MHF;		DMFE_DBUG(0, "Link Failed :", phy_mode);	}}/*   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 */	db->cr6_data &= ~CR6_FDM;	/* Clear Full Duplex Bit */	if (db->op_mode & 0x4)		db->cr6_data |= CR6_FDM;	if (!(db->media_mode & DMFE_AUTO)) {	/* Force Mode Check */		/* User force the media type */		phy_reg = phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id);		/* printk("Nway phy_reg5 %x ",phy_reg); */		if (phy_reg & 0x1) {			/* parter own the N-Way capability */			phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x1e0;			switch (db->op_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;			}			phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);		} else {			/* parter without the N-Way capability */			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);		}	}}/*   Write a word to Phy register */static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id){	u16 i;	u32 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(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;}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 },	{ 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:		dmfe_remove_one,};MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");MODULE_PARM(debug, "i");MODULE_PARM(mode, "i");MODULE_PARM(cr6set, "i");MODULE_PARM(chkmode, "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 0:	case 1:	case 4:	case 5:		dmfe_media_mode = mode;		break;	default:		dmfe_media_mode = 8;		break;	}	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. */ static void __exit dmfe_cleanup_module(void){	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 + -