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

📄 dm9000x.c

📁 linux-2.6.12下的百兆网卡芯片dm9000ae驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			ret = -EBUSY;			goto out;		}		ndev->base_addr = base;		ndev->irq = pdev->resource[1].start;				db->io_addr = (void *)base;		db->io_data = (void *)(base + 4);#ifdef CONFIG_MX1_SCB9328		db->outblk  = dm9000_outblk_16bit;		db->inblk   = dm9000_inblk_16bit;		db->dumpblk = dm9000_dumpblk_16bit;#endif		break;	case 3:		db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);		db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);		db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);		if (db->addr_res == NULL || db->data_res == NULL) {			printk(KERN_ERR PFX "insufficient resources\n");			ret = -ENOENT;			goto out;		}		i = res_size(db->addr_res);		db->addr_req = request_mem_region(db->addr_res->start, i,						  pdev->name);		if (db->addr_req == NULL) {			printk(KERN_ERR PFX "cannot claim address reg area\n");			ret = -EIO;			goto out;		}		db->io_addr = ioremap(db->addr_res->start, i);		if (db->io_addr == NULL) {			printk(KERN_ERR "failed to ioremap address reg\n");			ret = -EINVAL;			goto out;		}		iosize = res_size(db->data_res);		db->data_req = request_mem_region(db->data_res->start, iosize,						  pdev->name);		if (db->data_req == NULL) {			printk(KERN_ERR PFX "cannot claim data reg area\n");			ret = -EIO;			goto out;		}		db->io_data = ioremap(db->data_res->start, iosize);		if (db->io_data == NULL) {			printk(KERN_ERR "failed to ioremap data reg\n");			ret = -EINVAL;			goto out;		}		/* fill in parameters for net-dev structure */		ndev->base_addr = (unsigned long)db->io_addr;		ndev->irq	= db->irq_res->start;		/* ensure at least we have a default set of IO routines */		dmfe_set_io(db, iosize);		/* check to see if anything is being over-ridden */		if (pdata != NULL) {			/* check to see if the driver wants to over-ride the			 * default IO width */			if (pdata->flags & DM9000_PLATF_8BITONLY)				dmfe_set_io(db, 1);			if (pdata->flags & DM9000_PLATF_16BITONLY)				dmfe_set_io(db, 2);			if (pdata->flags & DM9000_PLATF_32BITONLY)				dmfe_set_io(db, 4);			/* check to see if there are any IO routine			 * over-rides */			if (pdata->inblk != NULL)				db->inblk = pdata->inblk;			if (pdata->outblk != NULL)				db->outblk = pdata->outblk;			if (pdata->dumpblk != NULL)				db->dumpblk = pdata->dumpblk;		}	}	dmfe_reset(db);	/* try two times, DM9000 sometimes gets the first read wrong */	for (i = 0; i < 2; i++) {		id_val  = ior(db, DMFE_VIDL);		id_val |= (u32)ior(db, DMFE_VIDH) << 8;		id_val |= (u32)ior(db, DMFE_PIDL) << 16;		id_val |= (u32)ior(db, DMFE_PIDH) << 24;		if (id_val == DM9000_ID)			break;		printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);	}	if (id_val != DM9000_ID) {		printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);		goto release;	}	/* from this point we assume that we have found a DM9000 */	/* driver system function */	ether_setup(ndev);	ndev->open		 = &dmfe_open;	ndev->hard_start_xmit    = &dmfe_start_xmit;	ndev->stop		 = &dmfe_stop;	ndev->get_stats		 = &dmfe_get_stats;	ndev->set_multicast_list = &dm9000_hash_table;	ndev->do_ioctl		 = &dmfe_do_ioctl;#ifdef DM9000_PROGRAM_EEPROM	program_eeprom(db);#endif	db->msg_enable       = NETIF_MSG_LINK;	db->mii.phy_id_mask  = 0x1f;	db->mii.reg_num_mask = 0x1f;	db->mii.force_media  = 0;	db->mii.full_duplex  = 0;	db->mii.dev	     = ndev;	db->mii.mdio_read    = dmfe_phy_read;	db->mii.mdio_write   = dmfe_phy_write;	/* Read SROM content */	for (i = 0; i < 64; i++)		((u16 *) db->srom)[i] = read_srom_word(db, i);	/* Set Node Address */	for (i = 0; i < 6; i++)		ndev->dev_addr[i] = ne_def_eth_mac_addr[i];	if (!is_valid_ether_addr(ndev->dev_addr))		printk("%s: Invalid ethernet MAC address.  Please "		       "set using ifconfig\n", ndev->name);	dev_set_drvdata(dev, ndev);	ret = register_netdev(ndev);	if (ret == 0) {		printk("%s: dm9000 at %p,%p IRQ %d MAC: ",		       ndev->name,  db->io_addr, db->io_data, ndev->irq);		for (i = 0; i < 5; i++)			printk("%02x:", ndev->dev_addr[i]);		printk("%02x\n", ndev->dev_addr[5]);	}	return 0; release: out:	printk("%s: not found (%d).\n", CARDNAME, ret);	dmfe_release_board(pdev, db);	kfree(ndev);	return ret;}/* *  Open the interface. *  The interface is opened whenever "ifconfig" actives it. */static intdmfe_open(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK2("entering dmfe_open\n");	if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev))		return -EAGAIN;	/* Disable all interrupts */	iow(db, DMFE_IMR, IMR_PAR);#ifdef CONFIG_MX1_SCB9328	set_irq_type(SCB9328_ETH_IRQ, __IRQT_LOWLVL);#endif	/* Initialize DM9000 board */	dmfe_reset(db);	dmfe_init_dm9000(dev);	/* Init driver variable */	db->dbug_cnt = 0;	db->runt_length_counter = 0;	db->long_length_counter = 0;	db->reset_counter = 0;	db->device_wait_reset = 0;	/* set and active a timer process */	init_timer(&db->timer);	db->timer.expires  = DMFE_TIMER_WUT * 2;	db->timer.data     = (unsigned long) dev;	db->timer.function = &dmfe_timer;	add_timer(&db->timer);	mii_check_media(&db->mii, netif_msg_link(db), 1);	netif_start_queue(dev);	/* Re-enable interrupt mask */	iow(db, DMFE_IMR, IMR_PAR | IMR_PTM | IMR_PRM);	return 0;}/*  * Set PHY operating mode */static voidset_PHY_mode(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;	if (!(db->op_mode & DM9000_AUTO)) {		switch (db->op_mode) {		case DM9000_10MHD:			phy_reg4 = ADVERTISE_10HALF | ADVERTISE_CSMA;			phy_reg0 = 0;			break;		case DM9000_10MFD:			phy_reg4 = ADVERTISE_10FULL | ADVERTISE_CSMA;			phy_reg0 = BMCR_ANENABLE | BMCR_FULLDPLX;			break;		case DM9000_100MHD:			phy_reg4 = ADVERTISE_100HALF | ADVERTISE_CSMA;			phy_reg0 = BMCR_SPEED100;			break;		case DM9000_100MFD:			phy_reg4 = ADVERTISE_100FULL | ADVERTISE_CSMA;			phy_reg0 =			    BMCR_SPEED100 | BMCR_ANENABLE | BMCR_FULLDPLX;			break;		}		dmfe_phy_write(dev, 0, MII_ADVERTISE, phy_reg4);	/* Set PHY media mode */		dmfe_phy_write(dev, 0, MII_BMCR, phy_reg0);	/*  Tmp */	}	iow(db, DMFE_GPCR, 0x01);	/* Let GPIO0 output */	iow(db, DMFE_GPR, 0x00);	/* Enable PHY */}/*  * Initilize dm9000 board */static voiddmfe_init_dm9000(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK1("entering %s\n",__FUNCTION__);	/* I/O mode */	db->io_mode = ior(db, DMFE_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */	/* GPIO0 on pre-activate PHY */	iow(db, DMFE_GPR, 0x00);	/*REG_1F bit0 activate phyxcer */	/* Set PHY */	db->op_mode = media_mode;	set_PHY_mode(dev);	/* Init needed register value */	db->reg0 = DM9000_REG00;	/* User passed argument */	db->reg5 = reg5;	db->reg8 = reg8;	db->reg9 = reg9;	db->rega = rega;	/* Program operating register */	iow(db, DMFE_NCR, db->reg0);	iow(db, DMFE_TCR, 0);	        /* TX Polling clear */	iow(db, DMFE_BPTR, 0x3f);	    /* Less 3Kb, 200us */	iow(db, DMFE_FCTR, db->reg9);	/* Flow Control : High/Low Water */	iow(db, DMFE_FCR, db->rega);	/* Flow Control */	iow(db, DMFE_SMCR, 0);	        /* Special Mode */	iow(db, DMFE_NSR, 0x2c);	    /* clear TX status */	iow(db, DMFE_ISR, ISR_CLR_STATUS); /* Clear interrupt status */	/* Set address filter table */	dm9000_hash_table(dev);	/* Activate DM9000 */	iow(db, DMFE_RCR, db->reg5 | 1);	/* RX enable */	iow(db, DMFE_IMR, DM9000_REGFF);	/* Enable TX/RX interrupt mask */	/* Init Driver variable */	db->tx_pkt_cnt = 0;	db->queue_pkt_len = 0;	dev->trans_start = 0;	spin_lock_init(&db->lock);}/* *  Hardware start transmission. *  Send a packet to media from the upper layer. */static intdmfe_start_xmit(struct sk_buff *skb, struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK3("dmfe_start_xmit\n");	if (db->tx_pkt_cnt > 1)		return 1;	netif_stop_queue(dev);	/* Disable all interrupts */	iow(db, DMFE_IMR, IMR_PAR);	/* Move data to DM9000 TX RAM */	writeb(DMFE_MWCMD, db->io_addr);	(db->outblk)(db->io_data, skb->data, skb->len);	/* 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, DMFE_TXPLL, skb->len & 0xff);		iow(db, DMFE_TXPLH, (skb->len >> 8) & 0xff);		/* Issue TX polling command */		iow(db, DMFE_TCR, TCR_TXREQ);	/* 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)		netif_wake_queue(dev);	/* Re-enable interrupt */	iow(db, DMFE_IMR, IMR_PAR | IMR_PTM | IMR_PRM);	return 0;}static voiddmfe_shutdown(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	/* RESET devie */	dmfe_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */	iow(db, DMFE_GPR, 0x01);	/* Power-Down PHY */	iow(db, DMFE_IMR, IMR_PAR);	/* Disable all interrupt */	iow(db, DMFE_RCR, 0x00);	/* Disable RX */}/*  Stop the interface.  The interface is stopped when it is brought.*/static intdmfe_stop(struct net_device *ndev){	board_info_t *db = (board_info_t *) ndev->priv;	PRINTK1("entering %s\n",__FUNCTION__);	/* deleted timer */	del_timer(&db->timer);	netif_stop_queue(ndev);	netif_carrier_off(ndev);	/* free interrupt */	free_irq(ndev->irq, ndev);	dmfe_shutdown(ndev);	return 0;}/*  DM9000 interrupt handler  receive the packet to upper layer, free the transmitted packet*/voiddmfe_tx_done(struct net_device *dev, board_info_t * db){	int tx_status = ior(db, DMFE_NSR);	/* Got TX status */	if (tx_status & 0xc) {		/* One packet sent complete */		db->tx_pkt_cnt--;		dev->trans_start = 0;		db->stats.tx_packets++;		/* Queue packet check & send */		if (db->tx_pkt_cnt > 0) {			iow(db, DMFE_TXPLL, db->queue_pkt_len & 0xff);			iow(db, DMFE_TXPLH, (db->queue_pkt_len >> 8) & 0xff);			iow(db, DMFE_TCR, TCR_TXREQ);			dev->trans_start = jiffies;		}		netif_wake_queue(dev);	}}static irqreturn_tdmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	board_info_t *db;	int int_status;	u8 reg_save;//	scb9328_ledon(4);	PRINTK3("entering %s\n",__FUNCTION__);	if (!dev) {		PRINTK1("dmfe_interrupt() without DEVICE arg\n");		return IRQ_HANDLED;	}   	/* A real interrupt coming */	db = (board_info_t *) dev->priv;	spin_lock(&db->lock);	/* Save previous register address */

⌨️ 快捷键说明

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